aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/EditableView.tsx
diff options
context:
space:
mode:
authorbobzel <zzzman@gmail.com>2023-05-13 09:55:48 -0400
committerbobzel <zzzman@gmail.com>2023-05-13 09:55:48 -0400
commitdca61505ba138eef3819b16b760ec81becf9329e (patch)
treef1bdf777d263760eea058ae0b6df40db831574a4 /src/client/views/EditableView.tsx
parent8b0fa2ca2c454468f04221f52951051253571556 (diff)
changed EditableViews to support oneline and multiline. Also added transformer UI to allow documents to be entered. changed transformer to write doc id's, not variables.. made schema view support oneline and fixed bug with docdecoration hader occluding things invisibly. updated web pages to be zoomable and for its anchors to update web page and scroll location properly. made autolinkanchor directly go to target on click.
Diffstat (limited to 'src/client/views/EditableView.tsx')
-rw-r--r--src/client/views/EditableView.tsx98
1 files changed, 79 insertions, 19 deletions
diff --git a/src/client/views/EditableView.tsx b/src/client/views/EditableView.tsx
index d1311a60a..6b4132814 100644
--- a/src/client/views/EditableView.tsx
+++ b/src/client/views/EditableView.tsx
@@ -1,9 +1,11 @@
import React = require('react');
-import { action, observable } from 'mobx';
+import { action, IReactionDisposer, observable, reaction } from 'mobx';
import { observer } from 'mobx-react';
import * as Autosuggest from 'react-autosuggest';
import { ObjectField } from '../../fields/ObjectField';
import './EditableView.scss';
+import { DocumentIconContainer } from './nodes/DocumentIcon';
+import { OverlayView } from './OverlayView';
export interface EditableProps {
/**
@@ -37,7 +39,8 @@ export interface EditableProps {
onChange: (e: React.ChangeEvent, { newValue }: { newValue: string }) => void;
autosuggestProps: Autosuggest.AutosuggestProps<string, any>;
};
- oneLine?: boolean;
+ oneLine?: boolean; // whether to display the editable view as a single input line or as a textarea
+ allowCRs?: boolean; // can carriage returns be entered
editing?: boolean;
isEditingCallback?: (isEditing: boolean) => void;
menuCallback?: (x: number, y: number) => void;
@@ -45,6 +48,7 @@ export interface EditableProps {
showMenuOnLoad?: boolean;
background?: string | undefined;
placeholder?: string;
+ wrap?: string; // nowrap, pre-wrap, etc
}
/**
@@ -55,7 +59,9 @@ export interface EditableProps {
@observer
export class EditableView extends React.Component<EditableProps> {
private _ref = React.createRef<HTMLDivElement>();
- private _inputref = React.createRef<HTMLInputElement>();
+ private _inputref: HTMLInputElement | HTMLTextAreaElement | null = null;
+ _overlayDisposer?: () => void;
+ _editingDisposer?: IReactionDisposer;
@observable _editing: boolean = false;
constructor(props: EditableProps) {
@@ -63,21 +69,53 @@ export class EditableView extends React.Component<EditableProps> {
this._editing = this.props.editing ? true : false;
}
+ componentDidMount(): void {
+ this._editingDisposer = reaction(
+ () => this._editing,
+ editing => {
+ if (editing) {
+ setTimeout(() => {
+ if (this._inputref?.value.startsWith('=') || this._inputref?.value.startsWith(':=')) {
+ this._overlayDisposer?.();
+ this._overlayDisposer = OverlayView.Instance.addElement(<DocumentIconContainer />, { x: 0, y: 0 });
+ }
+ });
+ } else {
+ this._overlayDisposer?.();
+ this._overlayDisposer = undefined;
+ }
+ },
+ { fireImmediately: true }
+ );
+ }
+
@action
componentDidUpdate() {
if (this._editing && this.props.editing === false) {
- this._inputref.current?.value && this.finalizeEdit(this._inputref.current.value, false, true, false);
+ this._inputref?.value && this.finalizeEdit(this._inputref.value, false, true, false);
} else if (this.props.editing !== undefined) {
this._editing = this.props.editing;
}
}
componentWillUnmount() {
- this._inputref.current?.value && this.finalizeEdit(this._inputref.current.value, false, true, false);
+ this._overlayDisposer?.();
+ this._editingDisposer?.();
+ this._inputref?.value && this.finalizeEdit(this._inputref.value, false, true, false);
}
+ onChange = (e: React.ChangeEvent) => {
+ const targVal = (e.target as any).value;
+ if (!(targVal.startsWith(':=') || targVal.startsWith('='))) {
+ this._overlayDisposer?.();
+ this._overlayDisposer = undefined;
+ } else if (!this._overlayDisposer) {
+ this._overlayDisposer = OverlayView.Instance.addElement(<DocumentIconContainer />, { x: 0, y: 0 });
+ }
+ };
+
@action
- onKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
+ onKeyDown = (e: React.KeyboardEvent<HTMLInputElement | HTMLTextAreaElement>) => {
switch (e.key) {
case 'Tab':
e.stopPropagation();
@@ -89,13 +127,15 @@ export class EditableView extends React.Component<EditableProps> {
if (!e.currentTarget.value) this.props.OnEmpty?.();
break;
case 'Enter':
- 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);
- this._editing = false;
- this.props.isEditingCallback?.(false);
+ 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);
+ this._editing = false;
+ this.props.isEditingCallback?.(false);
+ }
}
break;
case 'Escape':
@@ -103,9 +143,6 @@ export class EditableView extends React.Component<EditableProps> {
this._editing = false;
this.props.isEditingCallback?.(false);
break;
- case ':':
- this.props.menuCallback?.(e.currentTarget.getBoundingClientRect().x, e.currentTarget.getBoundingClientRect().y);
- break;
case 'ArrowUp':
case 'ArrowDown':
case 'ArrowLeft':
@@ -117,6 +154,12 @@ export class EditableView extends React.Component<EditableProps> {
case 'Meta':
case 'Control':
break;
+ case ':':
+ if (this.props.menuCallback) {
+ this.props.menuCallback(e.currentTarget.getBoundingClientRect().x, e.currentTarget.getBoundingClientRect().y);
+ break;
+ }
+
default:
if (this.props.textCallback?.(e.key)) {
this._editing = false;
@@ -186,15 +229,32 @@ export class EditableView extends React.Component<EditableProps> {
onChange: this.props.autosuggestProps.onChange,
}}
/>
- ) : (
+ ) : this.props.oneLine !== false && this.props.GetValue()?.toString().indexOf('\n') === -1 ? (
<input
className="editableView-input"
- ref={this._inputref}
+ 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}
onBlur={e => this.finalizeEdit(e.currentTarget.value, false, true, false)}
defaultValue={this.props.GetValue()}
autoFocus={true}
+ onChange={this.onChange}
+ onKeyDown={this.onKeyDown}
+ onKeyPress={this.stopPropagation}
+ onPointerDown={this.stopPropagation}
+ onClick={this.stopPropagation}
+ onPointerUp={this.stopPropagation}
+ />
+ ) : (
+ <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}
+ onBlur={e => this.finalizeEdit(e.currentTarget.value, false, true, false)}
+ defaultValue={this.props.GetValue()}
+ autoFocus={true}
+ onChange={this.onChange}
onKeyDown={this.onKeyDown}
onKeyPress={this.stopPropagation}
onPointerDown={this.stopPropagation}
@@ -220,7 +280,7 @@ export class EditableView extends React.Component<EditableProps> {
<div
className={`editableView-container-editing${this.props.oneLine ? '-oneLine' : ''}`}
ref={this._ref}
- style={{ display: this.props.display, textOverflow: this.props.overflow, minHeight: '10px', whiteSpace: 'nowrap', height: this.props.height || 'auto', maxHeight: this.props.maxHeight }}
+ style={{ 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 }}
//onPointerDown={this.stopPropagation}
onClick={this.onClick}
placeholder={this.props.placeholder}>