aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/EditableView.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views/EditableView.tsx')
-rw-r--r--src/client/views/EditableView.tsx116
1 files changed, 61 insertions, 55 deletions
diff --git a/src/client/views/EditableView.tsx b/src/client/views/EditableView.tsx
index abb7ed7ee..73ac1b032 100644
--- a/src/client/views/EditableView.tsx
+++ b/src/client/views/EditableView.tsx
@@ -1,10 +1,12 @@
-import React = require('react');
-import { action, IReactionDisposer, observable, reaction } from 'mobx';
+import { action, IReactionDisposer, makeObservable, observable, reaction } from 'mobx';
import { observer } from 'mobx-react';
+import * as React from 'react';
import * as Autosuggest from 'react-autosuggest';
import { ObjectField } from '../../fields/ObjectField';
import './EditableView.scss';
import { DocumentIconContainer } from './nodes/DocumentIcon';
+import { FieldView, FieldViewProps } from './nodes/FieldView';
+import { ObservableReactComponent } from './ObservableReactComponent';
import { OverlayView } from './OverlayView';
export interface EditableProps {
@@ -26,6 +28,7 @@ export interface EditableProps {
* The contents to render when not editing
*/
contents: any;
+ fieldContents?: FieldViewProps;
fontStyle?: string;
fontSize?: number;
height?: number | 'auto';
@@ -57,7 +60,7 @@ export interface EditableProps {
* of the content, and set the value based on the entered string.
*/
@observer
-export class EditableView extends React.Component<EditableProps> {
+export class EditableView extends ObservableReactComponent<EditableProps> {
private _ref = React.createRef<HTMLDivElement>();
private _inputref: HTMLInputElement | HTMLTextAreaElement | null = null;
_overlayDisposer?: () => void;
@@ -66,7 +69,8 @@ export class EditableView extends React.Component<EditableProps> {
constructor(props: EditableProps) {
super(props);
- this._editing = this.props.editing ? true : false;
+ makeObservable(this);
+ this._editing = this._props.editing ? true : false;
}
componentDidMount(): void {
@@ -89,12 +93,12 @@ export class EditableView extends React.Component<EditableProps> {
);
}
- @action
- componentDidUpdate() {
- if (this._editing && this.props.editing === false) {
+ componentDidUpdate(prevProps: Readonly<EditableProps>) {
+ super.componentDidUpdate(prevProps);
+ if (this._editing && this._props.editing === false) {
this._inputref?.value && this.finalizeEdit(this._inputref.value, false, true, false);
- } else if (this.props.editing !== undefined) {
- this._editing = this.props.editing;
+ } else if (this._props.editing !== undefined) {
+ this._editing = this._props.editing;
}
}
@@ -120,28 +124,28 @@ export class EditableView extends React.Component<EditableProps> {
case 'Tab':
e.stopPropagation();
this.finalizeEdit(e.currentTarget.value, e.shiftKey, false, false);
- this.props.OnTab?.(e.shiftKey);
+ this._props.OnTab?.(e.shiftKey);
break;
case 'Backspace':
e.stopPropagation();
- if (!e.currentTarget.value) this.props.OnEmpty?.();
+ if (!e.currentTarget.value) this._props.OnEmpty?.();
break;
case 'Enter':
- if (this.props.allowCRs !== true) {
+ if (this._props.allowCRs !== true) {
e.stopPropagation();
if (!e.ctrlKey) {
this.finalizeEdit(e.currentTarget.value, e.shiftKey, false, true);
- } else if (this.props.OnFillDown) {
- this.props.OnFillDown(e.currentTarget.value);
+ } else if (this._props.OnFillDown) {
+ this._props.OnFillDown(e.currentTarget.value);
this._editing = false;
- this.props.isEditingCallback?.(false);
+ this._props.isEditingCallback?.(false);
}
}
break;
case 'Escape':
e.stopPropagation();
this._editing = false;
- this.props.isEditingCallback?.(false);
+ this._props.isEditingCallback?.(false);
break;
case 'ArrowUp':
case 'ArrowDown':
@@ -155,30 +159,30 @@ export class EditableView extends React.Component<EditableProps> {
case 'Control':
break;
case ':':
- if (this.props.menuCallback) {
+ if (this._props.menuCallback) {
e.stopPropagation();
- this.props.menuCallback(e.currentTarget.getBoundingClientRect().x, e.currentTarget.getBoundingClientRect().y);
+ this._props.menuCallback(e.currentTarget.getBoundingClientRect().x, e.currentTarget.getBoundingClientRect().y);
break;
}
default:
- if (this.props.textCallback?.(e.key)) {
+ if (this._props.textCallback?.(e.key)) {
e.stopPropagation();
this._editing = false;
- this.props.isEditingCallback?.(false);
+ this._props.isEditingCallback?.(false);
}
}
};
@action
onClick = (e: React.MouseEvent) => {
- if (this.props.editing !== false) {
+ if (this._props.editing !== false) {
e.nativeEvent.stopPropagation();
- if (this._ref.current && this.props.showMenuOnLoad) {
- this.props.menuCallback?.(this._ref.current.getBoundingClientRect().x, this._ref.current.getBoundingClientRect().y);
+ if (this._ref.current && this._props.showMenuOnLoad) {
+ this._props.menuCallback?.(this._ref.current.getBoundingClientRect().x, this._ref.current.getBoundingClientRect().y);
} else {
this._editing = true;
- this.props.isEditingCallback?.(true);
+ this._props.isEditingCallback?.(true);
}
// e.stopPropagation();
}
@@ -186,17 +190,17 @@ export class EditableView extends React.Component<EditableProps> {
@action
finalizeEdit(value: string, shiftDown: boolean, lostFocus: boolean, enterKey: boolean) {
- if (this.props.SetValue(value, shiftDown, enterKey)) {
+ if (this._props.SetValue(value, shiftDown, enterKey)) {
this._editing = false;
- this.props.isEditingCallback?.(false);
+ this._props.isEditingCallback?.(false);
} else {
this._editing = false;
- this.props.isEditingCallback?.(false);
+ this._props.isEditingCallback?.(false);
!lostFocus &&
setTimeout(
action(() => {
this._editing = true;
- this.props.isEditingCallback?.(true);
+ this._props.isEditingCallback?.(true);
}),
0
);
@@ -215,30 +219,32 @@ export class EditableView extends React.Component<EditableProps> {
};
renderEditor() {
- return this.props.autosuggestProps ? (
+ return this._props.autosuggestProps ? (
<Autosuggest
- {...this.props.autosuggestProps.autosuggestProps}
+ {...this._props.autosuggestProps.autosuggestProps}
inputProps={{
className: 'editableView-input',
onKeyDown: this.onKeyDown,
autoFocus: true,
+ // @ts-ignore
onBlur: e => this.finalizeEdit(e.currentTarget.value, false, true, false),
onPointerDown: this.stopPropagation,
onClick: this.stopPropagation,
onPointerUp: this.stopPropagation,
onKeyPress: this.stopPropagation,
- value: this.props.autosuggestProps.value,
- onChange: this.props.autosuggestProps.onChange,
+ value: this._props.autosuggestProps.value,
+ // @ts-ignore
+ onChange: this._props.autosuggestProps.onChange,
}}
/>
- ) : this.props.oneLine !== false && this.props.GetValue()?.toString().indexOf('\n') === -1 ? (
+ ) : this._props.oneLine !== false && this._props.GetValue()?.toString().indexOf('\n') === -1 ? (
<input
className="editableView-input"
ref={r => (this._inputref = r)}
- style={{ display: this.props.display, overflow: 'auto', fontSize: this.props.fontSize, minWidth: 20, background: this.props.background }}
- placeholder={this.props.placeholder}
+ style={{ display: this._props.display, overflow: 'auto', fontSize: this._props.fontSize, minWidth: 20, background: this._props.background }}
+ placeholder={this._props.placeholder}
onBlur={e => this.finalizeEdit(e.currentTarget.value, false, true, false)}
- defaultValue={this.props.GetValue()}
+ defaultValue={this._props.GetValue()}
autoFocus={true}
onChange={this.onChange}
onKeyDown={this.onKeyDown}
@@ -251,10 +257,10 @@ export class EditableView extends React.Component<EditableProps> {
<textarea
className="editableView-input"
ref={r => (this._inputref = r)}
- style={{ display: this.props.display, overflow: 'auto', fontSize: this.props.fontSize, minHeight: `min(100%, ${(this.props.GetValue()?.split('\n').length || 1) * 15})`, minWidth: 20, background: this.props.background }}
- placeholder={this.props.placeholder}
+ style={{ display: this._props.display, overflow: 'auto', fontSize: this._props.fontSize, minHeight: `min(100%, ${(this._props.GetValue()?.split('\n').length || 1) * 15})`, minWidth: 20, background: this._props.background }}
+ placeholder={this._props.placeholder}
onBlur={e => this.finalizeEdit(e.currentTarget.value, false, true, false)}
- defaultValue={this.props.GetValue()}
+ defaultValue={this._props.GetValue()}
autoFocus={true}
onChange={this.onChange}
onKeyDown={this.onKeyDown}
@@ -267,9 +273,9 @@ export class EditableView extends React.Component<EditableProps> {
}
render() {
- const gval = this.props.GetValue()?.replace(/\n/g, '\\r\\n');
+ const gval = this._props.GetValue()?.replace(/\n/g, '\\r\\n');
if (this._editing && gval !== undefined) {
- return this.props.sizeToContent ? (
+ return this._props.sizeToContent ? (
<div style={{ display: 'grid', minWidth: 100 }}>
<div style={{ display: 'inline-block', position: 'relative', height: 0, width: '100%', overflow: 'hidden' }}>{gval}</div>
{this.renderEditor()}
@@ -278,30 +284,30 @@ export class EditableView extends React.Component<EditableProps> {
this.renderEditor()
);
}
- setTimeout(() => this.props.autosuggestProps?.resetValue());
- return this.props.contents instanceof ObjectField ? null : (
+ setTimeout(() => this._props.autosuggestProps?.resetValue());
+ return this._props.contents instanceof ObjectField ? null : (
<div
- className={`editableView-container-editing${this.props.oneLine ? '-oneLine' : ''}`}
+ className={`editableView-container-editing${this._props.oneLine ? '-oneLine' : ''}`}
ref={this._ref}
style={{
- display: this.props.display, //
- textOverflow: this.props.overflow,
+ display: this._props.display, //
+ textOverflow: this._props.overflow,
minHeight: '10px',
- whiteSpace: this.props.oneLine ? 'nowrap' : 'pre-line',
- height: this.props.height,
- maxHeight: this.props.maxHeight,
- fontStyle: this.props.fontStyle,
- fontSize: this.props.fontSize,
+ whiteSpace: this._props.oneLine ? 'nowrap' : 'pre-line',
+ height: this._props.height,
+ maxHeight: this._props.maxHeight,
+ fontStyle: this._props.fontStyle,
+ fontSize: this._props.fontSize,
}}
//onPointerDown={this.stopPropagation}
onClick={this.onClick}
- placeholder={this.props.placeholder}>
+ placeholder={this._props.placeholder}>
<span
style={{
- fontStyle: this.props.fontStyle,
- fontSize: this.props.fontSize,
+ fontStyle: this._props.fontStyle,
+ fontSize: this._props.fontSize,
}}>
- {this.props.contents ? this.props.contents?.valueOf() : this.props.placeholder?.valueOf()}
+ {this._props.fieldContents ? <FieldView {...this._props.fieldContents} /> : this.props.contents ? this._props.contents?.valueOf() : this._props.placeholder?.valueOf()}
</span>
</div>
);