diff options
-rw-r--r-- | src/client/documents/Documents.ts | 3 | ||||
-rw-r--r-- | src/client/util/DocumentManager.ts | 9 | ||||
-rw-r--r-- | src/client/util/ProsemirrorExampleTransfer.ts | 8 | ||||
-rw-r--r-- | src/client/util/RichTextRules.ts | 2 | ||||
-rw-r--r-- | src/client/util/RichTextSchema.tsx | 11 | ||||
-rw-r--r-- | src/client/views/nodes/FormattedTextBox.tsx | 31 |
6 files changed, 42 insertions, 22 deletions
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 50c51ace1..304eccc02 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -97,6 +97,7 @@ export interface DocumentOptions { schemaColumns?: List<SchemaHeaderField>; dockingConfig?: string; autoHeight?: boolean; + annotationOn?: Doc; removeDropProperties?: List<string>; // list of properties that should be removed from a document when it is dropped. e.g., a creator button may be forceActive to allow it be dragged, but the forceActive property can be removed from the dropped document dbDoc?: Doc; ischecked?: ScriptField; // returns whether a font icon box is checked @@ -316,7 +317,7 @@ export namespace Docs { */ export namespace Create { - const delegateKeys = ["x", "y", "width", "height", "panX", "panY", "nativeWidth", "nativeHeight", "dropAction", "forceActive", "fitWidth"]; + const delegateKeys = ["x", "y", "width", "height", "panX", "panY", "nativeWidth", "nativeHeight", "dropAction", "annotationOn", "forceActive", "fitWidth"]; /** * This function receives the relevant document prototype and uses diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts index 85303176f..60c251f0e 100644 --- a/src/client/util/DocumentManager.ts +++ b/src/client/util/DocumentManager.ts @@ -134,10 +134,13 @@ export class DocumentManager { finalDocView && Doc.linkFollowHighlight(finalDocView.props.Document); }; const docView = DocumentManager.Instance.getFirstDocumentView(targetDoc); - const annotatedDoc = await Cast(targetDoc.annotationOn, Doc); + let annotatedDoc = await Cast(docView?.props.Document.annotationOn, Doc); + if (annotatedDoc) { + let first = DocumentManager.Instance.getFirstDocumentView(annotatedDoc); + if (first) annotatedDoc = first.props.Document; + } if (docView) { // we have a docView already and aren't forced to create a new one ... just focus on the document. TODO move into view if necessary otherwise just highlight? - annotatedDoc && docView.props.focus(annotatedDoc, false); - docView.props.focus(docView.props.Document, willZoom); + docView.props.focus(annotatedDoc || docView.props.Document, false); highlight(); } else { const contextDocs = docContext ? await DocListCastAsync(docContext.data) : undefined; diff --git a/src/client/util/ProsemirrorExampleTransfer.ts b/src/client/util/ProsemirrorExampleTransfer.ts index 3324d8abe..b879ca7aa 100644 --- a/src/client/util/ProsemirrorExampleTransfer.ts +++ b/src/client/util/ProsemirrorExampleTransfer.ts @@ -6,6 +6,8 @@ import { liftListItem, sinkListItem } from "./prosemirrorPatches.js"; import { splitListItem, wrapInList, } from "prosemirror-schema-list"; import { EditorState, Transaction, TextSelection } from "prosemirror-state"; import { TooltipTextMenu } from "./TooltipTextMenu"; +import { SelectionManager } from "./SelectionManager"; +import { FormattedTextBox } from "../views/nodes/FormattedTextBox"; const mac = typeof navigator !== "undefined" ? /Mac/.test(navigator.platform) : false; @@ -46,7 +48,11 @@ export default function buildKeymap<S extends Schema<any>>(schema: S, mapKeys?: bind("Alt-ArrowUp", joinUp); bind("Alt-ArrowDown", joinDown); bind("Mod-BracketLeft", lift); - bind("Escape", selectParentNode); + bind("Escape", (state: EditorState<S>, dispatch: (tx: Transaction<S>) => void) => { + dispatch(state.tr.setSelection(TextSelection.create(state.doc, state.selection.from, state.selection.from))); + (document.activeElement as any).blur?.(); + SelectionManager.DeselectAll(); + }); bind("Mod-b", toggleMark(schema.marks.strong)); bind("Mod-B", toggleMark(schema.marks.strong)); diff --git a/src/client/util/RichTextRules.ts b/src/client/util/RichTextRules.ts index 62b20b3fa..5148af889 100644 --- a/src/client/util/RichTextRules.ts +++ b/src/client/util/RichTextRules.ts @@ -220,7 +220,7 @@ export const inpRules = { new InputRule( new RegExp(/%#$/), (state, match, start, end) => { - const target = Docs.Create.TextDocument({ width: 75, height: 35, backgroundColor: "yellow", autoHeight: true, fontSize: 9, title: "inline comment" }); + const target = Docs.Create.TextDocument({ width: 75, height: 35, backgroundColor: "yellow", annotationOn: FormattedTextBox.FocusedBox!.dataDoc, autoHeight: true, fontSize: 9, title: "inline comment" }); const node = (state.doc.resolve(start) as any).nodeAfter; const newNode = schema.nodes.dashComment.create({ docid: target[Id] }); const dashDoc = schema.nodes.dashDoc.create({ width: 75, height: 35, title: "dashDoc", docid: target[Id], float: "right" }); diff --git a/src/client/util/RichTextSchema.tsx b/src/client/util/RichTextSchema.tsx index 7a048ed0d..bede23cb2 100644 --- a/src/client/util/RichTextSchema.tsx +++ b/src/client/util/RichTextSchema.tsx @@ -765,14 +765,14 @@ export class DashDocView { renderDepth={1} PanelWidth={self._dashDoc[WidthSym]} PanelHeight={self._dashDoc[HeightSym]} - focus={emptyFunction} + focus={self._textBox.props.focus} backgroundColor={returnEmptyString} parentActive={returnFalse} whenActiveChanged={returnFalse} bringToFront={emptyFunction} zoomToScale={emptyFunction} getScale={returnOne} - dontRegisterView={true} + dontRegisterView={false} ContainingCollectionView={undefined} ContainingCollectionDoc={undefined} ContentScaling={this.contentScaling} @@ -780,7 +780,12 @@ export class DashDocView { } }); const self = this; - this._dashSpan.onkeydown = function (e: any) { }; + this._dashSpan.onkeydown = function (e: any) { + e.stopPropagation(); + if (e.key === "Tab" || e.key === "Enter") { + e.preventDefault(); + } + }; this._dashSpan.onkeypress = function (e: any) { e.stopPropagation(); }; this._dashSpan.onwheel = function (e: any) { e.preventDefault(); }; this._dashSpan.onkeyup = function (e: any) { e.stopPropagation(); }; diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index 662cc9aea..6d889b495 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -76,8 +76,8 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & public static blankState = () => EditorState.create(FormattedTextBox.Instance.config); public static Instance: FormattedTextBox; public static ToolTipTextMenu: TooltipTextMenu | undefined = undefined; + public ProseRef?: HTMLDivElement; private _ref: React.RefObject<HTMLDivElement> = React.createRef(); - private _proseRef?: HTMLDivElement; private _editorView: Opt<EditorView>; private _applyingChange: boolean = false; private _searchIndex = 0; @@ -244,7 +244,7 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & view.dispatch(view.state.tr.removeMark(start, end, nmark).addMark(start, end, nmark)); } protected createDropTarget = (ele: HTMLDivElement) => { - this._proseRef = ele; + this.ProseRef = ele; this.dropDisposer && this.dropDisposer(); ele && (this.dropDisposer = DragManager.MakeDropTarget(ele, this.drop.bind(this))); } @@ -571,7 +571,7 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & this._ruleFontSize = rules ? rules.size : 0; rules && setTimeout(() => { const view = this._editorView!; - if (this._proseRef) { + if (this.ProseRef) { const n = new NodeSelection(view.state.doc.resolve(0)); if (this._editorView!.state.doc.textContent === "") { view.dispatch(view.state.tr.setSelection(new TextSelection(view.state.doc.resolve(0), view.state.doc.resolve(2))). @@ -794,10 +794,10 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & startup = NumCast(doc[fieldKey], 99).toString(); } } - if (this._proseRef) { + if (this.ProseRef) { const self = this; this._editorView && this._editorView.destroy(); - this._editorView = new EditorView(this._proseRef, { + this._editorView = new EditorView(this.ProseRef, { state: field && field.Data ? EditorState.fromJSON(config, JSON.parse(field.Data)) : EditorState.create(config), handleScrollToSelection: (editorView) => { const ref = editorView.domAtPos(editorView.state.selection.from); @@ -874,7 +874,9 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & e.preventDefault(); } if (e.button === 0 && this.active(true) && !e.altKey && !e.ctrlKey && !e.metaKey) { - e.stopPropagation(); + if (e.clientX < this.ProseRef!.getBoundingClientRect().right) { // don't stop propagation if clicking in the sidebar + e.stopPropagation(); + } } if (e.button === 2 || (e.button === 0 && e.ctrlKey)) { e.preventDefault(); @@ -901,7 +903,7 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & this.tryUpdateHeight(); // see if we need to preserve the insertion point - const prosediv = this._proseRef?.children?.[0] as any; + const prosediv = this.ProseRef?.children?.[0] as any; const keeplocation = prosediv?.keeplocation; prosediv && (prosediv.keeplocation = undefined); const pos = this._editorView?.state.selection.$from.pos || 1; @@ -925,8 +927,8 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & this._editorView!.dispatch(this._editorView!.state.tr.setSelection(TextSelection.create(this._editorView!.state.doc, pcords.pos + 2))); e.preventDefault(); } - if (!node && this._proseRef) { - const lastNode = this._proseRef.children[this._proseRef.children.length - 1].children[this._proseRef.children[this._proseRef.children.length - 1].children.length - 1]; // get the last prosemirror div + if (!node && this.ProseRef) { + const lastNode = this.ProseRef.children[this.ProseRef.children.length - 1].children[this.ProseRef.children[this.ProseRef.children.length - 1].children.length - 1]; // get the last prosemirror div if (e.clientY > lastNode.getBoundingClientRect().bottom) { // if we clicked below the last prosemirror div, then set the selection to be the end of the document this._editorView!.dispatch(this._editorView!.state.tr.setSelection(TextSelection.create(this._editorView!.state.doc, this._editorView!.state.doc.content.size))); } @@ -1057,17 +1059,20 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & e.preventDefault(); return; } - if (!this._editorView!.state.selection.empty && e.key === "%") { - this._editorView!.state.schema.EnteringStyle = true; + let state = this._editorView!.state; + if (!state.selection.empty && e.key === "%") { + state.schema.EnteringStyle = true; e.preventDefault(); e.stopPropagation(); return; } - if (this._editorView!.state.selection.empty || !this._editorView!.state.schema.EnteringStyle) { - this._editorView!.state.schema.EnteringStyle = false; + if (state.selection.empty || !state.schema.EnteringStyle) { + state.schema.EnteringStyle = false; } if (e.key === "Escape") { + this._editorView!.dispatch(state.tr.setSelection(TextSelection.create(state.doc, state.selection.from, state.selection.from))); + (document.activeElement as any).blur?.(); SelectionManager.DeselectAll(); } e.stopPropagation(); |