aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/nodes/formattedText
diff options
context:
space:
mode:
authorbobzel <zzzman@gmail.com>2023-12-10 20:19:27 -0500
committerbobzel <zzzman@gmail.com>2023-12-10 20:19:27 -0500
commit380ee1acac1c0b7972d7d423cf804af146dc0edf (patch)
tree1d77244a600e6eb1fb6d56356b3ce01ca6add89d /src/client/views/nodes/formattedText
parentb7b7105fac83ec11480204c5c7ac0ae6579774e1 (diff)
massive changes to use mobx 6 which means not accessing props directly in @computed functions.
Diffstat (limited to 'src/client/views/nodes/formattedText')
-rw-r--r--src/client/views/nodes/formattedText/DashDocView.tsx2
-rw-r--r--src/client/views/nodes/formattedText/DashFieldView.tsx14
-rw-r--r--src/client/views/nodes/formattedText/EquationEditor.scss468
-rw-r--r--src/client/views/nodes/formattedText/EquationEditor.tsx8
-rw-r--r--src/client/views/nodes/formattedText/FormattedTextBox.tsx213
-rw-r--r--src/client/views/nodes/formattedText/RichTextMenu.tsx48
6 files changed, 622 insertions, 131 deletions
diff --git a/src/client/views/nodes/formattedText/DashDocView.tsx b/src/client/views/nodes/formattedText/DashDocView.tsx
index 4384c8958..6332b200d 100644
--- a/src/client/views/nodes/formattedText/DashDocView.tsx
+++ b/src/client/views/nodes/formattedText/DashDocView.tsx
@@ -82,7 +82,7 @@ export class DashDocViewInternal extends React.Component<IDashDocViewInternal> {
_spanRef = React.createRef<HTMLDivElement>();
_disposers: { [name: string]: IReactionDisposer } = {};
_textBox: FormattedTextBox;
- @observable _dashDoc: Doc | undefined;
+ @observable _dashDoc: Doc | undefined = undefined;
@observable _finalLayout: any;
@observable _width: number = 0;
@observable _height: number = 0;
diff --git a/src/client/views/nodes/formattedText/DashFieldView.tsx b/src/client/views/nodes/formattedText/DashFieldView.tsx
index a395296d0..19e14d5a7 100644
--- a/src/client/views/nodes/formattedText/DashFieldView.tsx
+++ b/src/client/views/nodes/formattedText/DashFieldView.tsx
@@ -25,7 +25,7 @@ export class DashFieldView {
node: any;
tbox: FormattedTextBox;
- unclickable = () => !this.tbox.props.isSelected() && this.node.marks.some((m: any) => m.type === this.tbox.EditorView?.state.schema.marks.linkAnchor && m.attrs.noPreview);
+ unclickable = () => !this.tbox._props.isSelected() && this.node.marks.some((m: any) => m.type === this.tbox.EditorView?.state.schema.marks.linkAnchor && m.attrs.noPreview);
constructor(node: any, view: any, getPos: any, tbox: FormattedTextBox) {
this.node = node;
this.tbox = tbox;
@@ -97,13 +97,13 @@ export class DashFieldViewInternal extends React.Component<IDashFieldViewInterna
_textBoxDoc: Doc;
_fieldKey: string;
_fieldStringRef = React.createRef<HTMLSpanElement>();
- @observable _dashDoc: Doc | undefined;
+ @observable _dashDoc: Doc | undefined = undefined;
@observable _expanded = false;
constructor(props: IDashFieldViewInternal) {
super(props);
this._fieldKey = this.props.fieldKey;
- this._textBoxDoc = this.props.tbox.props.Document;
+ this._textBoxDoc = this.props.tbox.Document;
if (this.props.docId) {
DocServer.GetRefField(this.props.docId).then(action(dashDoc => dashDoc instanceof Doc && (this._dashDoc = dashDoc)));
@@ -126,7 +126,7 @@ export class DashFieldViewInternal extends React.Component<IDashFieldViewInterna
deselectCell={emptyFunction}
selectCell={emptyFunction}
maxWidth={this.props.hideKey ? undefined : this.return100}
- columnWidth={this.props.hideKey ? () => this.props.tbox.props.PanelWidth() - 20 : returnZero}
+ columnWidth={this.props.hideKey ? () => this.props.tbox._props.PanelWidth() - 20 : returnZero}
selectedCell={() => [this._dashDoc!, 0]}
fieldKey={this._fieldKey}
rowHeight={returnZero}
@@ -145,7 +145,7 @@ export class DashFieldViewInternal extends React.Component<IDashFieldViewInterna
}
createPivotForField = (e: React.MouseEvent) => {
- let container = this.props.tbox.props.DocumentView?.().props.docViewPath().lastElement();
+ let container = this.props.tbox._props.DocumentView?.()._props.docViewPath().lastElement();
if (container) {
const embedding = Doc.MakeEmbedding(container.Document);
embedding._type_collection = CollectionViewType.Time;
@@ -157,7 +157,7 @@ export class DashFieldViewInternal extends React.Component<IDashFieldViewInterna
list.map(c => c.heading).indexOf(this._fieldKey) === -1 && list.push(new SchemaHeaderField(this._fieldKey, '#f1efeb'));
list.map(c => c.heading).indexOf('text') === -1 && list.push(new SchemaHeaderField('text', '#f1efeb'));
embedding._pivotField = this._fieldKey.startsWith('#') ? 'tags' : this._fieldKey;
- this.props.tbox.props.addDocTab(embedding, OpenWhere.addRight);
+ this.props.tbox._props.addDocTab(embedding, OpenWhere.addRight);
}
};
@@ -177,7 +177,7 @@ export class DashFieldViewInternal extends React.Component<IDashFieldViewInterna
style={{
width: this.props.width,
height: this.props.height,
- pointerEvents: this.props.tbox.props.isSelected() || this.props.tbox.isAnyChildContentActive?.() ? undefined : 'none',
+ pointerEvents: this.props.tbox._props.isSelected() || this.props.tbox.isAnyChildContentActive?.() ? undefined : 'none',
}}>
{this.props.hideKey ? null : (
<span className="dashFieldView-labelSpan" title="click to see related tags" onPointerDown={this.onPointerDownLabelSpan}>
diff --git a/src/client/views/nodes/formattedText/EquationEditor.scss b/src/client/views/nodes/formattedText/EquationEditor.scss
new file mode 100644
index 000000000..b0c17e56e
--- /dev/null
+++ b/src/client/views/nodes/formattedText/EquationEditor.scss
@@ -0,0 +1,468 @@
+// using this import, we get runtime errors when trying to load the specified font-faces
+// so we copy the .css and remove the @font-face imports
+
+// @import 'mathquill/build/mathquill.css'
+/*
+ * MathQuill v0.10.1 http://mathquill.com
+ * by Han, Jeanine, and Mary maintainers@mathquill.com
+ *
+ * This Source Code Form is subject to the terms of the
+ * Mozilla Public License, v. 2.0. If a copy of the MPL
+ * was not distributed with this file, You can obtain
+ * one at http://mozilla.org/MPL/2.0/.
+ */
+// @font-face {
+// font-family: Symbola;
+// src: url(font/Symbola.eot);
+// src:
+// local('Symbola Regular'),
+// local('Symbola'),
+// url(font/Symbola.woff2) format('woff2'),
+// url(font/Symbola.woff) format('woff'),
+// url(font/Symbola.ttf) format('truetype'),
+// url(font/Symbola.otf) format('opentype'),
+// url(font/Symbola.svg#Symbola) format('svg');
+// }
+.mq-editable-field {
+ display: -moz-inline-box;
+ display: inline-block;
+}
+.mq-editable-field .mq-cursor {
+ border-left: 1px solid black;
+ margin-left: -1px;
+ position: relative;
+ z-index: 1;
+ padding: 0;
+ display: -moz-inline-box;
+ display: inline-block;
+}
+.mq-editable-field .mq-cursor.mq-blink {
+ visibility: hidden;
+}
+.mq-editable-field,
+.mq-math-mode .mq-editable-field {
+ border: 1px solid gray;
+}
+.mq-editable-field.mq-focused,
+.mq-math-mode .mq-editable-field.mq-focused {
+ -webkit-box-shadow:
+ #8bd 0 0 1px 2px,
+ inset #6ae 0 0 2px 0;
+ -moz-box-shadow:
+ #8bd 0 0 1px 2px,
+ inset #6ae 0 0 2px 0;
+ box-shadow:
+ #8bd 0 0 1px 2px,
+ inset #6ae 0 0 2px 0;
+ border-color: #709ac0;
+ border-radius: 1px;
+}
+.mq-math-mode .mq-editable-field {
+ margin: 1px;
+}
+.mq-editable-field .mq-latex-command-input {
+ color: inherit;
+ font-family: 'Courier New', monospace;
+ border: 1px solid gray;
+ padding-right: 1px;
+ margin-right: 1px;
+ margin-left: 2px;
+}
+.mq-editable-field .mq-latex-command-input.mq-empty {
+ background: transparent;
+}
+.mq-editable-field .mq-latex-command-input.mq-hasCursor {
+ border-color: ActiveBorder;
+}
+.mq-editable-field.mq-empty:after,
+.mq-editable-field.mq-text-mode:after,
+.mq-math-mode .mq-empty:after {
+ visibility: hidden;
+ content: 'c';
+}
+.mq-editable-field .mq-cursor:only-child:after,
+.mq-editable-field .mq-textarea + .mq-cursor:last-child:after {
+ visibility: hidden;
+ content: 'c';
+}
+.mq-editable-field .mq-text-mode .mq-cursor:only-child:after {
+ content: '';
+}
+.mq-editable-field.mq-text-mode {
+ overflow-x: auto;
+ overflow-y: hidden;
+}
+.mq-root-block,
+.mq-math-mode .mq-root-block {
+ display: -moz-inline-box;
+ display: inline-block;
+ width: 100%;
+ padding: 2px;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+ white-space: nowrap;
+ overflow: hidden;
+ vertical-align: middle;
+}
+.mq-math-mode {
+ font-variant: normal;
+ font-weight: normal;
+ font-style: normal;
+ font-size: 115%;
+ line-height: 1;
+ display: -moz-inline-box;
+ display: inline-block;
+}
+.mq-math-mode .mq-non-leaf,
+.mq-math-mode .mq-scaled {
+ display: -moz-inline-box;
+ display: inline-block;
+}
+.mq-math-mode var,
+.mq-math-mode .mq-text-mode,
+.mq-math-mode .mq-nonSymbola {
+ font-family: 'Times New Roman', Symbola, serif;
+ line-height: 0.9;
+}
+.mq-math-mode * {
+ font-size: inherit;
+ line-height: inherit;
+ margin: 0;
+ padding: 0;
+ border-color: black;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ user-select: none;
+ box-sizing: border-box;
+}
+.mq-math-mode .mq-empty {
+ background: #ccc;
+}
+.mq-math-mode .mq-empty.mq-root-block {
+ background: transparent;
+}
+.mq-math-mode.mq-empty {
+ background: transparent;
+}
+.mq-math-mode .mq-text-mode {
+ display: inline-block;
+}
+.mq-math-mode .mq-text-mode.mq-hasCursor {
+ box-shadow: inset darkgray 0 0.1em 0.2em;
+ padding: 0 0.1em;
+ margin: 0 -0.1em;
+ min-width: 1ex;
+}
+.mq-math-mode .mq-font {
+ font:
+ 1em 'Times New Roman',
+ Symbola,
+ serif;
+}
+.mq-math-mode .mq-font * {
+ font-family: inherit;
+ font-style: inherit;
+}
+.mq-math-mode b,
+.mq-math-mode b.mq-font {
+ font-weight: bolder;
+}
+.mq-math-mode var,
+.mq-math-mode i,
+.mq-math-mode i.mq-font {
+ font-style: italic;
+}
+.mq-math-mode var.mq-f {
+ margin-right: 0.2em;
+ margin-left: 0.1em;
+}
+.mq-math-mode .mq-roman var.mq-f {
+ margin: 0;
+}
+.mq-math-mode big {
+ font-size: 200%;
+}
+.mq-math-mode .mq-int > big {
+ display: inline-block;
+ -webkit-transform: scaleX(0.7);
+ -moz-transform: scaleX(0.7);
+ -ms-transform: scaleX(0.7);
+ -o-transform: scaleX(0.7);
+ transform: scaleX(0.7);
+ vertical-align: -0.16em;
+}
+.mq-math-mode .mq-int > .mq-supsub {
+ font-size: 80%;
+ vertical-align: -1.1em;
+ padding-right: 0.2em;
+}
+.mq-math-mode .mq-int > .mq-supsub > .mq-sup > .mq-sup-inner {
+ vertical-align: 1.3em;
+}
+.mq-math-mode .mq-int > .mq-supsub > .mq-sub {
+ margin-left: -0.35em;
+}
+.mq-math-mode .mq-roman {
+ font-style: normal;
+}
+.mq-math-mode .mq-sans-serif {
+ font-family: sans-serif, Symbola, serif;
+}
+.mq-math-mode .mq-monospace {
+ font-family: monospace, Symbola, serif;
+}
+.mq-math-mode .mq-overline {
+ border-top: 1px solid black;
+ margin-top: 1px;
+}
+.mq-math-mode .mq-underline {
+ border-bottom: 1px solid black;
+ margin-bottom: 1px;
+}
+.mq-math-mode .mq-binary-operator {
+ padding: 0 0.2em;
+ display: -moz-inline-box;
+ display: inline-block;
+}
+.mq-math-mode .mq-supsub {
+ text-align: left;
+ font-size: 90%;
+ vertical-align: -0.5em;
+}
+.mq-math-mode .mq-supsub.mq-sup-only {
+ vertical-align: 0.5em;
+}
+.mq-math-mode .mq-supsub.mq-sup-only .mq-sup {
+ display: inline-block;
+ vertical-align: text-bottom;
+}
+.mq-math-mode .mq-supsub .mq-sup {
+ display: block;
+}
+.mq-math-mode .mq-supsub .mq-sub {
+ display: block;
+ float: left;
+}
+.mq-math-mode .mq-supsub .mq-binary-operator {
+ padding: 0 0.1em;
+}
+.mq-math-mode .mq-supsub .mq-fraction {
+ font-size: 70%;
+}
+.mq-math-mode sup.mq-nthroot {
+ font-size: 80%;
+ vertical-align: 0.8em;
+ margin-right: -0.6em;
+ margin-left: 0.2em;
+ min-width: 0.5em;
+}
+.mq-math-mode .mq-paren {
+ padding: 0 0.1em;
+ vertical-align: top;
+ -webkit-transform-origin: center 0.06em;
+ -moz-transform-origin: center 0.06em;
+ -ms-transform-origin: center 0.06em;
+ -o-transform-origin: center 0.06em;
+ transform-origin: center 0.06em;
+}
+.mq-math-mode .mq-paren.mq-ghost {
+ color: silver;
+}
+.mq-math-mode .mq-paren + span {
+ margin-top: 0.1em;
+ margin-bottom: 0.1em;
+}
+.mq-math-mode .mq-array {
+ vertical-align: middle;
+ text-align: center;
+}
+.mq-math-mode .mq-array > span {
+ display: block;
+}
+.mq-math-mode .mq-operator-name {
+ font-family: Symbola, 'Times New Roman', serif;
+ line-height: 0.9;
+ font-style: normal;
+}
+.mq-math-mode var.mq-operator-name.mq-first {
+ padding-left: 0.2em;
+}
+.mq-math-mode var.mq-operator-name.mq-last,
+.mq-math-mode .mq-supsub.mq-after-operator-name {
+ padding-right: 0.2em;
+}
+.mq-math-mode .mq-fraction {
+ font-size: 90%;
+ text-align: center;
+ vertical-align: -0.4em;
+ padding: 0 0.2em;
+}
+.mq-math-mode .mq-fraction,
+.mq-math-mode .mq-large-operator,
+.mq-math-mode x:-moz-any-link {
+ display: -moz-groupbox;
+}
+.mq-math-mode .mq-fraction,
+.mq-math-mode .mq-large-operator,
+.mq-math-mode x:-moz-any-link,
+.mq-math-mode x:default {
+ display: inline-block;
+}
+.mq-math-mode .mq-numerator,
+.mq-math-mode .mq-denominator {
+ display: block;
+}
+.mq-math-mode .mq-numerator {
+ padding: 0 0.1em;
+}
+.mq-math-mode .mq-denominator {
+ border-top: 1px solid;
+ float: right;
+ width: 100%;
+ padding: 0.1em;
+}
+.mq-math-mode .mq-sqrt-prefix {
+ padding-top: 0;
+ position: relative;
+ top: 0.1em;
+ vertical-align: top;
+ -webkit-transform-origin: top;
+ -moz-transform-origin: top;
+ -ms-transform-origin: top;
+ -o-transform-origin: top;
+ transform-origin: top;
+}
+.mq-math-mode .mq-sqrt-stem {
+ border-top: 1px solid;
+ margin-top: 1px;
+ padding-left: 0.15em;
+ padding-right: 0.2em;
+ margin-right: 0.1em;
+ padding-top: 1px;
+}
+.mq-math-mode .mq-vector-prefix {
+ display: block;
+ text-align: center;
+ line-height: 0.25em;
+ margin-bottom: -0.1em;
+ font-size: 0.75em;
+}
+.mq-math-mode .mq-vector-stem {
+ display: block;
+}
+.mq-math-mode .mq-large-operator {
+ vertical-align: -0.2em;
+ padding: 0.2em;
+ text-align: center;
+}
+.mq-math-mode .mq-large-operator .mq-from,
+.mq-math-mode .mq-large-operator big,
+.mq-math-mode .mq-large-operator .mq-to {
+ display: block;
+}
+.mq-math-mode .mq-large-operator .mq-from,
+.mq-math-mode .mq-large-operator .mq-to {
+ font-size: 80%;
+}
+.mq-math-mode .mq-large-operator .mq-from {
+ float: right;
+ /* take out of normal flow to manipulate baseline */
+ width: 100%;
+}
+.mq-math-mode,
+.mq-math-mode .mq-editable-field {
+ cursor: text;
+ font-family: Symbola, 'Times New Roman', serif;
+}
+.mq-math-mode .mq-overarrow {
+ border-top: 1px solid black;
+ margin-top: 1px;
+ padding-top: 0.2em;
+}
+.mq-math-mode .mq-overarrow:before {
+ display: block;
+ position: relative;
+ top: -0.34em;
+ font-size: 0.5em;
+ line-height: 0em;
+ content: '\27A4';
+ text-align: right;
+}
+.mq-math-mode .mq-overarrow.mq-arrow-left:before {
+ -moz-transform: scaleX(-1);
+ -o-transform: scaleX(-1);
+ -webkit-transform: scaleX(-1);
+ transform: scaleX(-1);
+ filter: FlipH;
+ -ms-filter: 'FlipH';
+}
+.mq-math-mode .mq-selection,
+.mq-editable-field .mq-selection,
+.mq-math-mode .mq-selection .mq-non-leaf,
+.mq-editable-field .mq-selection .mq-non-leaf,
+.mq-math-mode .mq-selection .mq-scaled,
+.mq-editable-field .mq-selection .mq-scaled {
+ background: #b4d5fe !important;
+ background: Highlight !important;
+ color: HighlightText;
+ border-color: HighlightText;
+}
+.mq-math-mode .mq-selection .mq-matrixed,
+.mq-editable-field .mq-selection .mq-matrixed {
+ background: #39f !important;
+}
+.mq-math-mode .mq-selection .mq-matrixed-container,
+.mq-editable-field .mq-selection .mq-matrixed-container {
+ filter: progid:DXImageTransform.Microsoft.Chroma(color='#3399FF') !important;
+}
+.mq-math-mode .mq-selection.mq-blur,
+.mq-editable-field .mq-selection.mq-blur,
+.mq-math-mode .mq-selection.mq-blur .mq-non-leaf,
+.mq-editable-field .mq-selection.mq-blur .mq-non-leaf,
+.mq-math-mode .mq-selection.mq-blur .mq-scaled,
+.mq-editable-field .mq-selection.mq-blur .mq-scaled,
+.mq-math-mode .mq-selection.mq-blur .mq-matrixed,
+.mq-editable-field .mq-selection.mq-blur .mq-matrixed {
+ background: #d4d4d4 !important;
+ color: black;
+ border-color: black;
+}
+.mq-math-mode .mq-selection.mq-blur .mq-matrixed-container,
+.mq-editable-field .mq-selection.mq-blur .mq-matrixed-container {
+ filter: progid:DXImageTransform.Microsoft.Chroma(color='#D4D4D4') !important;
+}
+.mq-editable-field .mq-textarea,
+.mq-math-mode .mq-textarea {
+ position: relative;
+ -webkit-user-select: text;
+ -moz-user-select: text;
+ user-select: text;
+}
+.mq-editable-field .mq-textarea *,
+.mq-math-mode .mq-textarea *,
+.mq-editable-field .mq-selectable,
+.mq-math-mode .mq-selectable {
+ -webkit-user-select: text;
+ -moz-user-select: text;
+ user-select: text;
+ position: absolute;
+ clip: rect(1em 1em 1em 1em);
+ -webkit-transform: scale(0);
+ -moz-transform: scale(0);
+ -ms-transform: scale(0);
+ -o-transform: scale(0);
+ transform: scale(0);
+ resize: none;
+ width: 1px;
+ height: 1px;
+}
+.mq-math-mode .mq-matrixed {
+ background: white;
+ display: -moz-inline-box;
+ display: inline-block;
+}
+.mq-math-mode .mq-matrixed-container {
+ filter: progid:DXImageTransform.Microsoft.Chroma(color='white');
+ margin-top: -0.1em;
+}
diff --git a/src/client/views/nodes/formattedText/EquationEditor.tsx b/src/client/views/nodes/formattedText/EquationEditor.tsx
index bde6c1315..07c70af77 100644
--- a/src/client/views/nodes/formattedText/EquationEditor.tsx
+++ b/src/client/views/nodes/formattedText/EquationEditor.tsx
@@ -3,8 +3,7 @@ import React, { Component, createRef } from 'react';
// Import JQuery, required for the functioning of the equation editor
import $ from 'jquery';
-// Import the styles from the Mathquill editor
-import 'mathquill/build/mathquill.css';
+import './EquationEditor.scss';
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
// @ts-ignore
@@ -14,6 +13,8 @@ window.jQuery = $;
// @ts-ignore
require('mathquill/build/mathquill');
+(window as any).MathQuill = (window as any).MathQuill.getInterface(1);
+
type EquationEditorProps = {
onChange(latex: string): void;
value: string;
@@ -74,8 +75,7 @@ class EquationEditor extends Component<EquationEditorProps> {
autoOperatorNames,
};
- // @ts-ignore
- this.mathField = (MathQuill as any).MathField(this.element.current, config);
+ this.mathField = (window as any).MathQuill.MathField(this.element.current, config);
this.mathField.latex(value || '');
}
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index 4f8e8769a..244de7849 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -2,7 +2,7 @@ import { IconProp } from '@fortawesome/fontawesome-svg-core';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { Tooltip } from '@mui/material';
import { isEqual } from 'lodash';
-import { action, computed, IReactionDisposer, observable, ObservableSet, reaction, runInAction } from 'mobx';
+import { action, computed, IReactionDisposer, makeObservable, observable, ObservableSet, override, reaction, runInAction } from 'mobx';
import { observer } from 'mobx-react';
import { baseKeymap, selectAll } from 'prosemirror-commands';
import { history } from 'prosemirror-history';
@@ -24,7 +24,7 @@ import { RichTextUtils } from '../../../../fields/RichTextUtils';
import { ComputedField } from '../../../../fields/ScriptField';
import { BoolCast, Cast, DocCast, FieldValue, NumCast, ScriptCast, StrCast } from '../../../../fields/Types';
import { GetEffectiveAcl, TraceMobx } from '../../../../fields/util';
-import { addStyleSheet, addStyleSheetRule, clearStyleSheetRules, emptyFunction, numberRange, returnFalse, returnZero, setupMoveUpEvents, smoothScroll, unimplementedFunction, Utils } from '../../../../Utils';
+import { addStyleSheet, addStyleSheetRule, clearStyleSheetRules, copyProps, emptyFunction, numberRange, returnFalse, returnZero, setupMoveUpEvents, smoothScroll, unimplementedFunction, Utils } from '../../../../Utils';
import { GoogleApiClientUtils, Pulls, Pushes } from '../../../apis/google_docs/GoogleApiClientUtils';
import { gptAPICall, GPTCallType } from '../../../apis/gpt/GPT';
import { DocServer } from '../../../DocServer';
@@ -129,7 +129,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
}
@computed get noSidebar() {
- return this.props.docViewPath().lastElement()?.props.hideDecorationTitle || this.props.noSidebar || this.Document._layout_noSidebar;
+ return this._props.docViewPath().lastElement()?._props.hideDecorationTitle || this._props.noSidebar || this.Document._layout_noSidebar;
}
@computed get layout_sidebarWidthPercent() {
return this._showSidebar ? '20%' : StrCast(this.layoutDoc._layout_sidebarWidthPercent, '0%');
@@ -138,7 +138,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
return StrCast(this.layoutDoc.sidebar_color, StrCast(this.layoutDoc[this.fieldKey + '_backgroundColor'], '#e4e4e4'));
}
@computed get layout_autoHeight() {
- return (this.props.forceAutoHeight || this.layoutDoc._layout_autoHeight) && !this.props.ignoreAutoHeight;
+ return (this._props.forceAutoHeight || this.layoutDoc._layout_autoHeight) && !this._props.ignoreAutoHeight;
}
@computed get textHeight() {
return NumCast(this.dataDoc[this.fieldKey + '_height']);
@@ -150,7 +150,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
return !this.sidebarWidth() ? 0 : NumCast(this.dataDoc[this.SidebarKey + '_height']);
}
@computed get titleHeight() {
- return this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.HeaderMargin) || 0;
+ return this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.HeaderMargin) || 0;
}
@computed get layout_autoHeightMargins() {
return this.titleHeight + NumCast(this.layoutDoc._layout_autoHeightMargins);
@@ -162,7 +162,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
!this.dataDoc[`${this.fieldKey}_recordingSource`] && (this.dataDoc.mediaState = value ? media_state.Recording : undefined);
}
@computed get config() {
- this._keymap = buildKeymap(schema, this.props);
+ this._keymap = buildKeymap(schema, this._props);
this._rules = new RichTextRules(this.Document, this);
return {
schema,
@@ -208,12 +208,20 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
return url.startsWith(document.location.origin) ? new URL(url).pathname.split('doc/').lastElement() : ''; // docId
}
- constructor(props: any) {
+ _prevProps: React.PropsWithChildren<FieldViewProps & FormattedTextBoxProps>;
+ @override _props: React.PropsWithChildren<FieldViewProps & FormattedTextBoxProps>;
+ constructor(props: React.PropsWithChildren<FieldViewProps & FormattedTextBoxProps>) {
super(props);
+ this._props = this._prevProps = props;
+ makeObservable(this);
FormattedTextBox.Instance = this;
this._recordingStart = Date.now();
}
+ componentDidUpdate() {
+ copyProps(this);
+ }
+
// removes all hyperlink anchors for the removed linkDoc
// TODO: bcz: Argh... if a section of text has multiple anchors, this should just remove the intended one.
// but since removing one anchor from the list of attr anchors isn't implemented, this will end up removing nothing.
@@ -315,10 +323,10 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
return target;
};
- DragManager.StartAnchorAnnoDrag([ele], new DragManager.AnchorAnnoDragData(this.props.docViewPath().lastElement(), () => this.getAnchor(true), targetCreator), e.pageX, e.pageY);
+ DragManager.StartAnchorAnnoDrag([ele], new DragManager.AnchorAnnoDragData(this._props.docViewPath().lastElement(), () => this.getAnchor(true), targetCreator), e.pageX, e.pageY);
});
const coordsB = this._editorView!.coordsAtPos(this._editorView!.state.selection.to);
- this.props.rootSelected?.() && AnchorMenu.Instance.jumpTo(coordsB.left, coordsB.bottom);
+ this._props.rootSelected?.() && AnchorMenu.Instance.jumpTo(coordsB.left, coordsB.bottom);
let ele: Opt<HTMLDivElement> = undefined;
try {
const contents = window.getSelection()?.getRangeAt(0).cloneContents();
@@ -361,7 +369,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
textChange && (dataDoc[this.fieldKey + '_modificationDate'] = new DateField(new Date(Date.now())));
if ((!prevData && !protoData) || newText || (!newText && !templateData)) {
// if no template, or there's text that didn't come from the layout template, write it to the document. (if this is driven by a template, then this overwrites the template text which is intended)
- if ((this._finishingLink || this.props.isContentActive()) && removeSelection(newJson) !== removeSelection(prevData?.Data)) {
+ if ((this._finishingLink || this._props.isContentActive()) && removeSelection(newJson) !== removeSelection(prevData?.Data)) {
const numstring = NumCast(dataDoc[this.fieldKey], null);
dataDoc[this.fieldKey] = numstring !== undefined ? Number(newText) : new RichTextField(newJson, newText);
dataDoc[this.fieldKey + '_noTemplate'] = true; // mark the data field as being split from the template if it has been edited
@@ -390,7 +398,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
this._editorView.updateState(EditorState.fromJSON(this.config, json));
}
}
- if (window.getSelection()?.isCollapsed && this.props.rootSelected?.()) {
+ if (window.getSelection()?.isCollapsed && this._props.rootSelected?.()) {
AnchorMenu.Instance.fadeOut(true);
}
}
@@ -438,7 +446,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
autoLink = () => {
const newAutoLinks = new Set<Doc>();
- const oldAutoLinks = LinkManager.Links(this.props.Document).filter(link => link.link_relationship === LinkManager.AutoKeywords);
+ const oldAutoLinks = LinkManager.Links(this._props.Document).filter(link => link.link_relationship === LinkManager.AutoKeywords);
if (this._editorView?.state.doc.textContent) {
const isNodeSel = this._editorView.state.selection instanceof NodeSelection;
const f = this._editorView.state.selection.from;
@@ -456,7 +464,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
updateTitle = () => {
const title = StrCast(this.dataDoc.title, Cast(this.dataDoc.title, RichTextField, null)?.Text);
if (
- !this.props.dontRegisterView && // (this.props.Document.isTemplateForField === "text" || !this.props.Document.isTemplateForField) && // only update the title if the data document's data field is changing
+ !this._props.dontRegisterView && // (this._props.Document.isTemplateForField === "text" || !this._props.Document.isTemplateForField) && // only update the title if the data document's data field is changing
(title.startsWith('-') || title.startsWith('@')) &&
this._editorView &&
!this.dataDoc.title_custom &&
@@ -499,7 +507,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
DocUtils.MakeLink(this.Document, target, { link_relationship: LinkManager.AutoKeywords })!);
newAutoLinks.add(alink);
// DocCast(alink.link_anchor_1).followLinkLocation = 'add:right';
- const allAnchors = [{ href: Doc.localServerPath(target), title: 'a link', anchorId: this.props.Document[Id] }];
+ const allAnchors = [{ href: Doc.localServerPath(target), title: 'a link', anchorId: this._props.Document[Id] }];
allAnchors.push(...(node.marks.find((m: Mark) => m.type.name === schema.marks.autoLinkAnchor.name)?.attrs.allAnchors ?? []));
const link = editorView.state.schema.marks.autoLinkAnchor.create({ allAnchors, title: 'auto term' });
tr = tr.addMark(pos, pos + node.nodeSize, link);
@@ -568,7 +576,6 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
};
@undoBatch
- @action
drop = (e: Event, de: DragManager.DropEvent) => {
if (de.complete.annoDragData) {
de.complete.annoDragData.dropDocCreator = () => this.getAnchor(true);
@@ -584,7 +591,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
// replace text contents when dragging with Alt
if (de.altKey) {
const fieldKey = Doc.LayoutFieldKey(draggedDoc);
- if (draggedDoc[fieldKey] instanceof RichTextField && !Doc.AreProtosEqual(draggedDoc, this.props.Document)) {
+ if (draggedDoc[fieldKey] instanceof RichTextField && !Doc.AreProtosEqual(draggedDoc, this._props.Document)) {
Doc.GetProto(this.dataDoc)[this.fieldKey] = Field.Copy(draggedDoc[fieldKey]);
}
@@ -742,9 +749,9 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
);
};
sidebarMove = (e: PointerEvent, down: number[], delta: number[]) => {
- const localDelta = this.props
+ const localDelta = this._props
.ScreenToLocalTransform()
- .scale(this.props.NativeDimScaling?.() || 1)
+ .scale(this._props.NativeDimScaling?.() || 1)
.transformDirection(delta[0], delta[1]);
const sidebarWidth = (NumCast(this.layoutDoc._width) * Number(this.layout_sidebarWidthPercent.replace('%', ''))) / 100;
const width = NumCast(this.layoutDoc._width) + localDelta[0];
@@ -758,15 +765,15 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
deleteAnnotation = (anchor: Doc) => {
const batch = UndoManager.StartBatch('delete link');
LinkManager.Instance.deleteLink(LinkManager.Links(anchor)[0]);
- // const docAnnotations = DocListCast(this.props.dataDoc[this.fieldKey]);
- // this.props.dataDoc[this.fieldKey] = new List<Doc>(docAnnotations.filter(a => a !== this.annoTextRegion));
+ // const docAnnotations = DocListCast(this._props.dataDoc[this.fieldKey]);
+ // this._props.dataDoc[this.fieldKey] = new List<Doc>(docAnnotations.filter(a => a !== this.annoTextRegion));
// AnchorMenu.Instance.fadeOut(true);
- this.props.select(false);
+ this._props.select(false);
setTimeout(batch.end); // wait for reaction to remove link from document
};
@undoBatch
- pinToPres = (anchor: Doc) => this.props.pinToPres(anchor, {});
+ pinToPres = (anchor: Doc) => this._props.pinToPres(anchor, {});
@undoBatch
makeTargetToggle = (anchor: Doc) => (anchor.followLinkToggle = !anchor.followLinkToggle);
@@ -776,7 +783,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
const trail = DocCast(anchor.presentationTrail);
if (trail) {
Doc.ActivePresentation = trail;
- this.props.addDocTab(trail, OpenWhere.replaceRight);
+ this._props.addDocTab(trail, OpenWhere.replaceRight);
}
};
@@ -913,7 +920,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
const optionItems = options && 'subitems' in options ? options.subitems : [];
optionItems.push({ description: `Generate Dall-E Image`, event: () => this.generateImage(), icon: 'star' });
optionItems.push({ description: `Ask GPT-3`, event: () => this.askGPT(), icon: 'lightbulb' });
- this.props.renderDepth &&
+ this._props.renderDepth &&
optionItems.push({
description: !this.Document._createDocOnCR ? 'Create New Doc on Carriage Return' : 'Allow Carriage Returns',
event: () => (this.layoutDoc._createDocOnCR = !this.layoutDoc._createDocOnCR),
@@ -958,7 +965,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
generateImage = async () => {
GPTPopup.Instance?.setTextAnchor(this.getAnchor(false));
GPTPopup.Instance?.setImgTargetDoc(this.Document);
- GPTPopup.Instance.addToCollection = this.props.addDocument;
+ GPTPopup.Instance.addToCollection = this._props.addDocument;
GPTPopup.Instance.setImgDesc((this.dataDoc.text as RichTextField)?.Text);
GPTPopup.Instance.generateImage();
};
@@ -1127,7 +1134,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
setTimeout(() => clearStyleSheetRules(FormattedTextBox._highlightStyleSheet), Math.max(this._focusSpeed || 0, 3000));
return focusSpeed;
} else {
- return this.props.focus(this.Document, options);
+ return this._props.focus(this.Document, options);
}
}
};
@@ -1141,10 +1148,10 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
};
@computed get contentScaling() {
- return Doc.NativeAspect(this.Document, this.dataDoc, false) ? this.props.NativeDimScaling?.() || 1 : 1;
+ return Doc.NativeAspect(this.Document, this.dataDoc, false) ? this._props.NativeDimScaling?.() || 1 : 1;
}
componentDidMount() {
- !this.props.dontSelectOnLoad && this.props.setContentView?.(this); // this tells the DocumentView that this AudioBox is the "content" of the document. this allows the DocumentView to indirectly call getAnchor() on the AudioBox when making a link.
+ !this._props.dontSelectOnLoad && this._props.setContentView?.(this); // this tells the DocumentView that this AudioBox is the "content" of the document. this allows the DocumentView to indirectly call getAnchor() on the AudioBox when making a link.
this._cachedLinks = LinkManager.Links(this.Document);
this._disposers.breakupDictation = reaction(() => Doc.RecordingEvent, this.breakupDictation);
this._disposers.layout_autoHeight = reaction(
@@ -1157,7 +1164,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
{ fireImmediately: true }
);
this._disposers.width = reaction(
- () => this.props.PanelWidth(),
+ () => this._props.PanelWidth(),
width => this.tryUpdateScrollHeight()
);
this._disposers.scrollHeight = reaction(
@@ -1171,13 +1178,13 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
({ sidebarHeight, textHeight, layout_autoHeight, marginsHeight }) => {
const newHeight = this.contentScaling * (marginsHeight + Math.max(sidebarHeight, textHeight));
if (
- (!Array.from(FormattedTextBox._globalHighlights).includes('Bold Text') || this.props.isSelected()) && //
+ (!Array.from(FormattedTextBox._globalHighlights).includes('Bold Text') || this._props.isSelected()) && //
layout_autoHeight &&
newHeight &&
newHeight !== this.layoutDoc.height &&
- !this.props.dontRegisterView
+ !this._props.dontRegisterView
) {
- this.props.setHeight?.(newHeight);
+ this._props.setHeight?.(newHeight);
}
},
{ fireImmediately: !Array.from(FormattedTextBox._globalHighlights).includes('Bold Text') }
@@ -1219,7 +1226,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
}
);
this._disposers.pullDoc = reaction(
- () => this.props.Document[Pulls],
+ () => this._props.Document[Pulls],
() => {
if (!DocumentButtonBar.hasPulledHack) {
DocumentButtonBar.hasPulledHack = true;
@@ -1228,7 +1235,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
}
);
this._disposers.pushDoc = reaction(
- () => this.props.Document[Pushes],
+ () => this._props.Document[Pushes],
() => {
if (!DocumentButtonBar.hasPushedHack) {
DocumentButtonBar.hasPushedHack = true;
@@ -1244,7 +1251,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
);
this._disposers.selected = reaction(
- () => this.props.rootSelected?.(),
+ () => this._props.rootSelected?.(),
action(selected => {
//selected && setTimeout(() => this.prepareForTyping());
if (FormattedTextBox._globalHighlights.has('Bold Text')) {
@@ -1254,14 +1261,14 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
RichTextMenu.Instance?.updateMenu(undefined, undefined, undefined, undefined);
}
if (this._editorView && selected) {
- RichTextMenu.Instance?.updateMenu(this._editorView, undefined, this.props, this.layoutDoc);
+ RichTextMenu.Instance?.updateMenu(this._editorView, undefined, this._props, this.layoutDoc);
setTimeout(this.autoLink, 20);
}
}),
{ fireImmediately: true }
);
- if (!this.props.dontRegisterView) {
+ if (!this._props.dontRegisterView) {
this._disposers.record = reaction(
() => this._recordingDictation,
() => {
@@ -1276,7 +1283,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
this._disposers.scroll = reaction(
() => NumCast(this.layoutDoc._layout_scrollTop),
pos => {
- if (!this._ignoreScroll && this._scrollRef.current && !this.props.dontSelectOnLoad) {
+ if (!this._ignoreScroll && this._scrollRef.current && !this._props.dontSelectOnLoad) {
const viewTrans = quickScroll ?? StrCast(this.Document._viewTransition);
const durationMiliStr = viewTrans.match(/([0-9]*)ms/);
const durationSecStr = viewTrans.match(/([0-9.]*)s/);
@@ -1439,8 +1446,8 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
const self = this;
return new Plugin({
view(newView) {
- runInAction(() => self.props.rootSelected?.() && RichTextMenu.Instance && (RichTextMenu.Instance.view = newView));
- return new RichTextMenuPlugin({ editorProps: this.props });
+ runInAction(() => self._props.rootSelected?.() && RichTextMenu.Instance && (RichTextMenu.Instance.view = newView));
+ return new RichTextMenuPlugin({ editorProps: this._props });
},
});
}
@@ -1462,7 +1469,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
const botOff = docPos.bottom > viewRect.bottom ? docPos.bottom - viewRect.bottom : undefined;
if (((topOff && Math.abs(Math.trunc(topOff)) > 0) || (botOff && Math.abs(Math.trunc(botOff)) > 0)) && scrollRef) {
const shift = Math.min(topOff ?? Number.MAX_VALUE, botOff ?? Number.MAX_VALUE);
- const scrollPos = scrollRef.scrollTop + shift * self.props.ScreenToLocalTransform().Scale;
+ const scrollPos = scrollRef.scrollTop + shift * self._props.ScreenToLocalTransform().Scale;
if (this._focusSpeed !== undefined) {
scrollPos && (this._scrollStopper = smoothScroll(this._focusSpeed, scrollRef, scrollPos, 'ease', this._scrollStopper));
} else {
@@ -1514,11 +1521,11 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
(this._editorView as any).TextView = this;
}
- const selectOnLoad = Doc.AreProtosEqual(this.props.TemplateDataDocument ?? this.Document, FormattedTextBox.SelectOnLoad) && (!LightboxView.LightboxDoc || LightboxView.IsLightboxDocView(this.props.docViewPath()));
- if (this._editorView && selectOnLoad && !this.props.dontRegisterView && !this.props.dontSelectOnLoad && this.isActiveTab(this.ProseRef)) {
+ const selectOnLoad = Doc.AreProtosEqual(this._props.TemplateDataDocument ?? this.Document, FormattedTextBox.SelectOnLoad) && (!LightboxView.LightboxDoc || LightboxView.IsLightboxDocView(this._props.docViewPath()));
+ if (this._editorView && selectOnLoad && !this._props.dontRegisterView && !this._props.dontSelectOnLoad && this.isActiveTab(this.ProseRef)) {
const selLoadChar = FormattedTextBox.SelectOnLoadChar;
FormattedTextBox.SelectOnLoad = undefined;
- this.props.select(false);
+ this._props.select(false);
if (selLoadChar) {
const $from = this._editorView.state.selection.anchor ? this._editorView.state.doc.resolve(this._editorView.state.selection.anchor - 1) : undefined;
const mark = schema.marks.user_mark.create({ userid: Doc.CurrentUserEmail, modified: Math.floor(Date.now() / 1000) });
@@ -1534,7 +1541,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
}
}
selectOnLoad && this._editorView!.focus();
- if (this.props.isContentActive()) this.prepareForTyping();
+ if (this._props.isContentActive()) this.prepareForTyping();
if (this._editorView) {
const tr = this._editorView.state.tr;
const { from, to } = tr.selection;
@@ -1557,15 +1564,14 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
...(Doc.UserDoc().fontColor !== 'transparent' && Doc.UserDoc().fontColor ? [schema.mark(schema.marks.pFontColor, { color: StrCast(Doc.UserDoc().fontColor) })] : []),
...(Doc.UserDoc().fontStyle === 'italics' ? [schema.mark(schema.marks.em)] : []),
...(Doc.UserDoc().textDecoration === 'underline' ? [schema.mark(schema.marks.underline)] : []),
- ...(Doc.UserDoc().fontFamily ? [schema.mark(schema.marks.pFontFamily, { family: this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.FontFamily) })] : []),
- ...(Doc.UserDoc().fontSize ? [schema.mark(schema.marks.pFontSize, { fontSize: this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.FontSize) })] : []),
+ ...(Doc.UserDoc().fontFamily ? [schema.mark(schema.marks.pFontFamily, { family: this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.FontFamily) })] : []),
+ ...(Doc.UserDoc().fontSize ? [schema.mark(schema.marks.pFontSize, { fontSize: this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.FontSize) })] : []),
...(Doc.UserDoc().fontWeight === 'bold' ? [schema.mark(schema.marks.strong)] : []),
...[schema.marks.user_mark.create({ userid: Doc.CurrentUserEmail, modified: Math.floor(Date.now() / 1000) })],
];
this._editorView?.dispatch(this._editorView?.state.tr.setStoredMarks(docDefaultMarks));
};
- @action
componentWillUnmount() {
if (this._recordingDictation) {
this._recordingDictation = !this._recordingDictation;
@@ -1598,7 +1604,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
const func = () => {
const docView = DocumentManager.Instance.getDocumentView(audiodoc);
if (!docView) {
- this.props.addDocTab(audiodoc, OpenWhere.addBottom);
+ this._props.addDocTab(audiodoc, OpenWhere.addBottom);
setTimeout(func);
} else docView.ComponentView?.playFrom?.(timecode, Cast(anchor.timecodeToHide, 'number', null)); // bcz: would be nice to find the next audio tag in the doc and play until that
};
@@ -1614,7 +1620,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
this._downTime = Date.now();
this._hadDownFocus = this.ProseRef?.children[0].className.includes('focused') ?? false;
FormattedTextBoxComment.textBox = this;
- if (e.button === 0 && this.props.rootSelected?.() && !e.altKey && !e.ctrlKey && !e.metaKey) {
+ if (e.button === 0 && this._props.rootSelected?.() && !e.altKey && !e.ctrlKey && !e.metaKey) {
if (e.clientX < this.ProseRef!.getBoundingClientRect().right) {
// stop propagation if not in sidebar, otherwise nested boxes will lose focus to outer boxes.
e.stopPropagation(); // if the text box's content is active, then it consumes all down events
@@ -1636,7 +1642,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
}
if (!state || !editor || !this.ProseRef?.children[0].className.includes('-focused')) return;
if (!state.selection.empty && !(state.selection instanceof NodeSelection)) this.setupAnchorMenu();
- else if (this.props.isContentActive(true)) {
+ else if (this._props.isContentActive(true)) {
const pcords = editor.posAtCoords({ left: e.clientX, top: e.clientY });
let xpos = pcords?.pos || 0;
while (xpos > 0 && !state.doc.resolve(xpos).node()?.isTextblock) {
@@ -1651,7 +1657,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
@action
onDoubleClick = (e: React.MouseEvent): void => {
FormattedTextBoxComment.textBox = this;
- if (e.button === 0 && this.props.rootSelected?.() && !e.altKey && !e.ctrlKey && !e.metaKey) {
+ if (e.button === 0 && this._props.rootSelected?.() && !e.altKey && !e.ctrlKey && !e.metaKey) {
if (e.clientX < this.ProseRef!.getBoundingClientRect().right) {
// stop propagation if not in sidebar
e.stopPropagation(); // if the text box is selected, then it consumes all click events
@@ -1662,7 +1668,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
}
FormattedTextBoxComment.Hide();
- if (e.buttons === 1 && this.props.rootSelected?.() && !e.altKey) {
+ if (e.buttons === 1 && this._props.rootSelected?.() && !e.altKey) {
e.stopPropagation();
}
};
@@ -1673,14 +1679,13 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
};
@action
onFocused = (e: React.FocusEvent): void => {
- console.log('FOCUSED = ' + this.layoutDoc.title + ' ' + this.props.rootSelected?.());
//applyDevTools.applyDevTools(this._editorView);
- this.ProseRef?.children[0] === e.nativeEvent.target && this._editorView && RichTextMenu.Instance?.updateMenu(this._editorView, undefined, this.props, this.layoutDoc);
+ this.ProseRef?.children[0] === e.nativeEvent.target && this._editorView && RichTextMenu.Instance?.updateMenu(this._editorView, undefined, this._props, this.layoutDoc);
e.stopPropagation();
};
onClick = (e: React.MouseEvent): void => {
- if (!this.props.isContentActive()) return;
+ if (!this._props.isContentActive()) return;
if ((e.nativeEvent as any).handledByInnerReactInstance) {
e.stopPropagation();
return;
@@ -1709,7 +1714,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
this._editorView!.dispatch(this._editorView!.state.tr.setSelection(NodeSelection.create(this._editorView!.state.doc, pcords.pos)));
}
}
- if (this.props.rootSelected?.()) {
+ if (this._props.rootSelected?.()) {
// if text box is selected, then it consumes all click events
(e.nativeEvent as any).handledByInnerReactInstance = true;
this.hitBulletTargets(e.clientX, e.clientY, !this._editorView?.state.selection.empty || this._forceUncollapse, false, this._forceDownNode, e.shiftKey);
@@ -1723,7 +1728,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
clearStyleSheetRules(FormattedTextBox._bulletStyleSheet);
const clickPos = this._editorView!.posAtCoords({ left: x, top: y });
let olistPos = clickPos?.pos;
- if (clickPos && olistPos && this.props.rootSelected?.()) {
+ if (clickPos && olistPos && this._props.rootSelected?.()) {
const clickNode = this._editorView?.state.doc.nodeAt(olistPos);
const nodeBef = this._editorView?.state.doc.nodeAt(Math.max(0, olistPos - 1));
olistPos = nodeBef?.type === this._editorView?.state.schema.nodes.ordered_list ? olistPos - 1 : olistPos;
@@ -1772,7 +1777,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
tr && this._editorView.dispatch(tr);
}
}
- if (RichTextMenu.Instance?.view === this._editorView && !this.props.rootSelected?.()) {
+ if (RichTextMenu.Instance?.view === this._editorView && !this._props.rootSelected?.()) {
RichTextMenu.Instance?.updateMenu(undefined, undefined, undefined, undefined);
}
FormattedTextBox._hadSelection = window.getSelection()?.toString() !== '';
@@ -1797,7 +1802,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
if ((e.altKey || e.ctrlKey) && e.key === 't') {
e.preventDefault();
e.stopPropagation();
- this.props.setTitleFocus?.();
+ this._props.setTitleFocus?.();
return;
}
const state = this._editorView!.state;
@@ -1851,7 +1856,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
};
onScroll = (e: React.UIEvent) => {
if (!LinkDocPreview.LinkInfo && this._scrollRef.current) {
- if (!this.props.dontSelectOnLoad) {
+ if (!this._props.dontSelectOnLoad) {
this._ignoreScroll = true;
this.layoutDoc._layout_scrollTop = this._scrollRef.current.scrollTop;
this._ignoreScroll = false;
@@ -1861,7 +1866,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
}
};
tryUpdateScrollHeight = () => {
- const margins = 2 * NumCast(this.layoutDoc._yMargin, this.props.yPadding || 0);
+ const margins = 2 * NumCast(this.layoutDoc._yMargin, this._props.yPadding || 0);
const children = this.ProseRef?.children.length ? Array.from(this.ProseRef.children[0].children) : undefined;
if (children && !SnappingManager.GetIsDragging()) {
const toNum = (val: string) => Number(val.replace('px', '').replace('auto', '0'));
@@ -1871,7 +1876,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
};
const proseHeight = !this.ProseRef ? 0 : children.reduce((p, child) => p + toHgt(child), margins);
const scrollHeight = this.ProseRef && Math.min(NumCast(this.layoutDoc.layout_maxAutoHeight, proseHeight), proseHeight);
- if (this.props.setHeight && scrollHeight && !this.props.dontRegisterView) {
+ if (this._props.setHeight && scrollHeight && !this._props.dontRegisterView) {
// if top === 0, then the text box is growing upward (as the overlay caption) which doesn't contribute to the height computation
const setScrollHeight = () => (this.dataDoc[this.fieldKey + '_scrollHeight'] = scrollHeight);
@@ -1883,8 +1888,8 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
}
}
};
- fitContentsToBox = () => BoolCast(this.props.Document._freeform_fitContentsToBox);
- sidebarContentScaling = () => (this.props.NativeDimScaling?.() || 1) * NumCast(this.layoutDoc._freeform_scale, 1);
+ fitContentsToBox = () => BoolCast(this._props.Document._freeform_fitContentsToBox);
+ sidebarContentScaling = () => (this._props.NativeDimScaling?.() || 1) * NumCast(this.layoutDoc._freeform_scale, 1);
sidebarAddDocument = (doc: Doc | Doc[], sidebarKey: string = this.SidebarKey) => {
if (!this.layoutDoc._layout_showSidebar) this.toggleSidebar();
return this.addDocument(doc, sidebarKey);
@@ -1892,12 +1897,12 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
sidebarMoveDocument = (doc: Doc | Doc[], targetCollection: Doc | undefined, addDocument: (doc: Doc | Doc[]) => boolean) => this.moveDocument(doc, targetCollection, addDocument, this.SidebarKey);
sidebarRemDocument = (doc: Doc | Doc[]) => this.removeDocument(doc, this.SidebarKey);
setSidebarHeight = (height: number) => (this.dataDoc[this.SidebarKey + '_height'] = height);
- sidebarWidth = () => (Number(this.layout_sidebarWidthPercent.substring(0, this.layout_sidebarWidthPercent.length - 1)) / 100) * this.props.PanelWidth();
+ sidebarWidth = () => (Number(this.layout_sidebarWidthPercent.substring(0, this.layout_sidebarWidthPercent.length - 1)) / 100) * this._props.PanelWidth();
sidebarScreenToLocal = () =>
- this.props
+ this._props
.ScreenToLocalTransform()
- .translate(-(this.props.PanelWidth() - this.sidebarWidth()) / (this.props.NativeDimScaling?.() || 1), 0)
- .scale(1 / NumCast(this.layoutDoc._freeform_scale, 1) / (this.props.NativeDimScaling?.() || 1));
+ .translate(-(this._props.PanelWidth() - this.sidebarWidth()) / (this._props.NativeDimScaling?.() || 1), 0)
+ .scale(1 / NumCast(this.layoutDoc._freeform_scale, 1) / (this._props.NativeDimScaling?.() || 1));
@computed get audioHandle() {
return !this._recordingDictation ? null : (
@@ -1920,9 +1925,9 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
TraceMobx();
const annotated = DocListCast(this.dataDoc[this.SidebarKey]).filter(d => d?.author).length;
const color = !annotated ? Colors.WHITE : Colors.BLACK;
- const backgroundColor = !annotated ? (this.sidebarWidth() ? Colors.MEDIUM_BLUE : Colors.BLACK) : this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.WidgetColor + (annotated ? ':annotated' : ''));
+ const backgroundColor = !annotated ? (this.sidebarWidth() ? Colors.MEDIUM_BLUE : Colors.BLACK) : this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.WidgetColor + (annotated ? ':annotated' : ''));
- return !annotated && (!this.props.isContentActive() || SnappingManager.GetIsDragging() || Doc.ActiveTool !== InkTool.None) ? null : (
+ return !annotated && (!this._props.isContentActive() || SnappingManager.GetIsDragging() || Doc.ActiveTool !== InkTool.None) ? null : (
<div
className="formattedTextBox-sidebar-handle"
onPointerDown={this.sidebarDown}
@@ -1941,7 +1946,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
return ComponentTag === CollectionStackingView ? (
<SidebarAnnos
ref={this._sidebarRef}
- {...this.props}
+ {...this._props}
Document={this.Document}
layoutDoc={this.layoutDoc}
dataDoc={this.dataDoc}
@@ -1958,14 +1963,14 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
setHeight={this.setSidebarHeight}
/>
) : (
- <div onPointerDown={e => setupMoveUpEvents(this, e, returnFalse, emptyFunction, () => SelectionManager.SelectView(this.props.DocumentView?.()!, false), true)}>
+ <div onPointerDown={e => setupMoveUpEvents(this, e, returnFalse, emptyFunction, () => SelectionManager.SelectView(this._props.DocumentView?.()!, false), true)}>
<ComponentTag
- {...this.props}
+ {...this._props}
ref={this._sidebarTagRef as any}
setContentView={emptyFunction}
NativeWidth={returnZero}
NativeHeight={returnZero}
- PanelHeight={this.props.PanelHeight}
+ PanelHeight={this._props.PanelHeight}
PanelWidth={this.sidebarWidth}
xPadding={0}
yPadding={0}
@@ -1979,7 +1984,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
moveDocument={this.sidebarMoveDocument}
addDocument={this.sidebarAddDocument}
ScreenToLocalTransform={this.sidebarScreenToLocal}
- renderDepth={this.props.renderDepth + 1}
+ renderDepth={this._props.renderDepth + 1}
setHeight={this.setSidebarHeight}
fitContentsToBox={this.fitContentsToBox}
noSidebar={true}
@@ -1997,12 +2002,12 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
}
cycleAlternateText = () => {
if (this.layoutDoc._layout_enableAltContentUI) {
- const usePath = this.layoutDoc[`_${this.props.fieldKey}_usePath`];
- this.layoutDoc[`_${this.props.fieldKey}_usePath`] = usePath === undefined ? 'alternate' : usePath === 'alternate' ? 'alternate:hover' : undefined;
+ const usePath = this.layoutDoc[`_${this._props.fieldKey}_usePath`];
+ this.layoutDoc[`_${this._props.fieldKey}_usePath`] = usePath === undefined ? 'alternate' : usePath === 'alternate' ? 'alternate:hover' : undefined;
}
};
@computed get overlayAlternateIcon() {
- const usePath = this.layoutDoc[`_${this.props.fieldKey}_usePath`];
+ const usePath = this.layoutDoc[`_${this._props.fieldKey}_usePath`];
return (
<Tooltip
title={
@@ -2024,7 +2029,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
className="formattedTextBox-alternateButton"
onPointerDown={e => setupMoveUpEvents(e.target, e, returnFalse, emptyFunction, e => this.cycleAlternateText())}
style={{
- display: this.props.isContentActive() && !SnappingManager.GetIsDragging() ? 'flex' : 'none',
+ display: this._props.isContentActive() && !SnappingManager.GetIsDragging() ? 'flex' : 'none',
background: usePath === undefined ? 'white' : usePath === 'alternate' ? 'black' : 'gray',
color: usePath === undefined ? 'black' : 'white',
}}>
@@ -2033,9 +2038,9 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
</Tooltip>
);
}
- @computed get fieldKey() {
- const usePath = StrCast(this.layoutDoc[`${this.props.fieldKey}_usePath`]);
- return this.props.fieldKey + (usePath && (!usePath.includes(':hover') || this._isHovering || this.props.isContentActive()) ? `_${usePath.replace(':hover', '')}` : '');
+ get fieldKey() {
+ const usePath = StrCast(this.layoutDoc[`${this._props.fieldKey}_usePath`]);
+ return this._props.fieldKey + (usePath && (!usePath.includes(':hover') || this._isHovering || this._props.isContentActive()) ? `_${usePath.replace(':hover', '')}` : '');
}
@observable _isHovering = false;
onPassiveWheel = (e: WheelEvent) => {
@@ -2049,14 +2054,14 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
}
// if scrollTop is 0, then don't let wheel trigger scroll on any container (which it would since onScroll won't be triggered on this)
- if (this.props.isContentActive()) {
- const scale = this.props.NativeDimScaling?.() || 1;
- const styleFromLayoutString = Doc.styleFromLayoutString(this.Document, this.props, scale); // this converts any expressions in the format string to style props. e.g., <FormattedTextBox height='{this._headerHeight}px' >
+ if (this._props.isContentActive()) {
+ const scale = this._props.NativeDimScaling?.() || 1;
+ const styleFromLayoutString = Doc.styleFromLayoutString(this.Document, this._props, scale); // this converts any expressions in the format string to style props. e.g., <FormattedTextBox height='{this._headerHeight}px' >
const height = Number(styleFromLayoutString.height?.replace('px', ''));
// prevent default if selected || child is active but this doc isn't scrollable
if (
- (this._scrollRef.current?.scrollHeight ?? 0) <= Math.ceil((height ? height : this.props.PanelHeight()) / scale) && //
- (this.props.rootSelected?.() || this.isAnyChildContentActive())
+ (this._scrollRef.current?.scrollHeight ?? 0) <= Math.ceil((height ? height : this._props.PanelHeight()) / scale) && //
+ (this._props.rootSelected?.() || this.isAnyChildContentActive())
) {
e.preventDefault();
}
@@ -2065,25 +2070,25 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
};
_oldWheel: any;
@computed get fontColor() {
- return this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.Color);
+ return this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.Color);
}
@computed get fontSize() {
- return this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.FontSize);
+ return this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.FontSize);
}
@computed get fontFamily() {
- return this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.FontFamily);
+ return this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.FontFamily);
}
@computed get fontWeight() {
- return this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.FontWeight);
+ return this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.FontWeight);
}
render() {
TraceMobx();
- const scale = (this.props.NativeDimScaling?.() || 1) * NumCast(this.layoutDoc._freeform_scale, 1);
+ const scale = (this._props.NativeDimScaling?.() || 1) * NumCast(this.layoutDoc._freeform_scale, 1);
const rounded = StrCast(this.layoutDoc.layout_borderRounding) === '100%' ? '-rounded' : '';
- setTimeout(() => !this.props.isContentActive() && FormattedTextBoxComment.textBox === this && FormattedTextBoxComment.Hide);
- const paddingX = NumCast(this.layoutDoc._xMargin, this.props.xPadding || 0);
- const paddingY = NumCast(this.layoutDoc._yMargin, this.props.yPadding || 0);
- const styleFromLayoutString = Doc.styleFromLayoutString(this.Document, this.props, scale); // this converts any expressions in the format string to style props. e.g., <FormattedTextBox height='{this._headerHeight}px' >
+ setTimeout(() => !this._props.isContentActive() && FormattedTextBoxComment.textBox === this && FormattedTextBoxComment.Hide);
+ const paddingX = NumCast(this.layoutDoc._xMargin, this._props.xPadding || 0);
+ const paddingY = NumCast(this.layoutDoc._yMargin, this._props.yPadding || 0);
+ const styleFromLayoutString = Doc.styleFromLayoutString(this.Document, this._props, scale); // this converts any expressions in the format string to style props. e.g., <FormattedTextBox height='{this._headerHeight}px' >
return styleFromLayoutString?.height === '0px' ? null : (
<div
className="formattedTextBox"
@@ -2095,7 +2100,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
r?.addEventListener('wheel', this.onPassiveWheel, { passive: false });
}}
style={{
- ...(this.props.dontScale
+ ...(this._props.dontScale
? {}
: {
transform: `scale(${scale})`,
@@ -2114,9 +2119,9 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
className="formattedTextBox-cont"
ref={this._ref}
style={{
- cursor: this.props.isContentActive() ? 'text' : undefined,
- height: this.props.height ? 'max-content' : undefined,
- pointerEvents: Doc.ActiveTool === InkTool.None && !this.props.onBrowseClick?.() ? undefined : 'none',
+ cursor: this._props.isContentActive() ? 'text' : undefined,
+ height: this._props.height ? 'max-content' : undefined,
+ pointerEvents: Doc.ActiveTool === InkTool.None && !this._props.onBrowseClick?.() ? undefined : 'none',
}}
onContextMenu={this.specificContextMenu}
onKeyDown={this.onKeyDown}
@@ -2131,7 +2136,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
className="formattedTextBox-outer"
ref={this._scrollRef}
style={{
- width: this.props.dontSelectOnLoad || this.noSidebar ? '100%' : `calc(100% - ${this.layout_sidebarWidthPercent})`,
+ width: this._props.dontSelectOnLoad || this.noSidebar ? '100%' : `calc(100% - ${this.layout_sidebarWidthPercent})`,
overflow: this.layoutDoc._createDocOnCR ? 'hidden' : this.layoutDoc._layout_autoHeight ? 'visible' : undefined,
}}
onScroll={this.onScroll}
@@ -2148,8 +2153,8 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
}}
/>
</div>
- {this.noSidebar || this.props.dontSelectOnLoad || !this.SidebarShown || this.layout_sidebarWidthPercent === '0%' ? null : this.sidebarCollection}
- {this.noSidebar || this.Document._layout_noSidebar || this.props.dontSelectOnLoad || this.Document._createDocOnCR || this.layoutDoc._chromeHidden ? null : this.sidebarHandle}
+ {this.noSidebar || this._props.dontSelectOnLoad || !this.SidebarShown || this.layout_sidebarWidthPercent === '0%' ? null : this.sidebarCollection}
+ {this.noSidebar || this.Document._layout_noSidebar || this._props.dontSelectOnLoad || this.Document._createDocOnCR || this.layoutDoc._chromeHidden ? null : this.sidebarHandle}
{this.audioHandle}
{this.layoutDoc._layout_enableAltContentUI && !this.layoutDoc._chromeHidden ? this.overlayAlternateIcon : null}
</div>
diff --git a/src/client/views/nodes/formattedText/RichTextMenu.tsx b/src/client/views/nodes/formattedText/RichTextMenu.tsx
index 7ce06cf7f..d7e799161 100644
--- a/src/client/views/nodes/formattedText/RichTextMenu.tsx
+++ b/src/client/views/nodes/formattedText/RichTextMenu.tsx
@@ -1,7 +1,7 @@
import * as React from 'react';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { Tooltip } from '@mui/material';
-import { action, computed, IReactionDisposer, observable, reaction, runInAction } from 'mobx';
+import { action, computed, IReactionDisposer, makeObservable, observable, override, reaction, runInAction } from 'mobx';
import { observer } from 'mobx-react';
import { lift, wrapIn } from 'prosemirror-commands';
import { Mark, MarkType, Node as ProsNode, ResolvedPos } from 'prosemirror-model';
@@ -10,7 +10,7 @@ import { EditorState, NodeSelection, TextSelection } from 'prosemirror-state';
import { EditorView } from 'prosemirror-view';
import { Doc } from '../../../../fields/Doc';
import { BoolCast, Cast, StrCast } from '../../../../fields/Types';
-import { numberRange } from '../../../../Utils';
+import { copyProps, numberRange } from '../../../../Utils';
import { DocServer } from '../../../DocServer';
import { LinkManager } from '../../../util/LinkManager';
import { SelectionManager } from '../../../util/SelectionManager';
@@ -63,8 +63,12 @@ export class RichTextMenu extends AntimodeMenu<AntimodeMenuProps> {
@observable private showLinkDropdown: boolean = false;
_reaction: IReactionDisposer | undefined;
- constructor(props: Readonly<{}>) {
+ _prevProps: AntimodeMenuProps;
+ @override _props: AntimodeMenuProps;
+ constructor(props: AntimodeMenuProps) {
super(props);
+ this._props = this._prevProps = props;
+ makeObservable(this);
runInAction(() => {
RichTextMenu.Instance = this;
this.updateMenu(undefined, undefined, props, this.layoutDoc);
@@ -107,6 +111,9 @@ export class RichTextMenu extends AntimodeMenu<AntimodeMenuProps> {
return BoolCast(this.layoutDoc?.layout_centered);
}
_disposer: IReactionDisposer | undefined;
+ componentDidUpdate() {
+ copyProps(this);
+ }
componentDidMount() {
this._disposer = reaction(
() => SelectionManager.Views().slice(),
@@ -361,7 +368,7 @@ export class RichTextMenu extends AntimodeMenu<AntimodeMenuProps> {
} else if (SelectionManager.Views().some(dv => dv.ComponentView instanceof EquationBox)) {
SelectionManager.Views().forEach(dv => (dv.Document._text_fontSize = fontSize));
} else Doc.UserDoc().fontSize = fontSize;
- this.updateMenu(this.view, undefined, this.props, this.layoutDoc);
+ this.updateMenu(this.view, undefined, this._props, this.layoutDoc);
};
setFontFamily = (family: string) => {
@@ -370,7 +377,7 @@ export class RichTextMenu extends AntimodeMenu<AntimodeMenuProps> {
this.setMark(fmark, this.view.state, (tx: any) => this.view!.dispatch(tx.addStoredMark(fmark)), true);
this.view.focus();
} else Doc.UserDoc().fontFamily = family;
- this.updateMenu(this.view, undefined, this.props, this.layoutDoc);
+ this.updateMenu(this.view, undefined, this._props, this.layoutDoc);
};
setHighlight(color: string) {
@@ -379,7 +386,7 @@ export class RichTextMenu extends AntimodeMenu<AntimodeMenuProps> {
this.setMark(highlightMark, this.view.state, (tx: any) => this.view!.dispatch(tx.addStoredMark(highlightMark)), true);
this.view.focus();
} else Doc.UserDoc()._fontHighlight = color;
- this.updateMenu(this.view, undefined, this.props, this.layoutDoc);
+ this.updateMenu(this.view, undefined, this._props, this.layoutDoc);
}
setColor(color: string) {
@@ -388,7 +395,7 @@ export class RichTextMenu extends AntimodeMenu<AntimodeMenuProps> {
this.setMark(colorMark, this.view.state, (tx: any) => this.view!.dispatch(tx.addStoredMark(colorMark)), true);
this.view.focus();
} else Doc.UserDoc().fontColor = color;
- this.updateMenu(this.view, undefined, this.props, this.layoutDoc);
+ this.updateMenu(this.view, undefined, this._props, this.layoutDoc);
}
// TODO: remove doesn't work
@@ -429,7 +436,7 @@ export class RichTextMenu extends AntimodeMenu<AntimodeMenuProps> {
}
}
this.view.focus();
- this.updateMenu(this.view, undefined, this.props, this.layoutDoc);
+ this.updateMenu(this.view, undefined, this._props, this.layoutDoc);
};
insertSummarizer(state: EditorState, dispatch: any) {
@@ -669,7 +676,6 @@ export class RichTextMenu extends AntimodeMenu<AntimodeMenuProps> {
};
@undoBatch
- @action
deleteLink = () => {
if (this.view) {
const linkAnchor = this.view.state.selection.$from.nodeAfter?.marks.find(m => m.type === this.view!.state.schema.marks.linkAnchor);
@@ -816,6 +822,18 @@ export class ButtonDropdown extends React.Component<ButtonDropdownProps> {
@observable private showDropdown: boolean = false;
private ref: HTMLDivElement | null = null;
+ _prevProps: React.PropsWithChildren<ButtonDropdownProps>;
+ @observable _props: React.PropsWithChildren<ButtonDropdownProps>;
+ constructor(props: React.PropsWithChildren<ButtonDropdownProps>) {
+ super(props);
+ this._props = this._prevProps = props;
+ makeObservable(this);
+ }
+
+ componentDidUpdate() {
+ copyProps(this);
+ }
+
componentDidMount() {
document.addEventListener('pointerdown', this.onBlur);
}
@@ -850,22 +868,22 @@ export class ButtonDropdown extends React.Component<ButtonDropdownProps> {
render() {
return (
<div className="button-dropdown-wrapper" ref={node => (this.ref = node)}>
- {!this.props.pdf ? (
- <div className="antimodeMenu-button dropdown-button-combined" onPointerDown={this.props.openDropdownOnButton ? this.onDropdownClick : undefined}>
- {this.props.button}
- <div style={{ marginTop: '-8.5', position: 'relative' }} onPointerDown={!this.props.openDropdownOnButton ? this.onDropdownClick : undefined}>
+ {!this._props.pdf ? (
+ <div className="antimodeMenu-button dropdown-button-combined" onPointerDown={this._props.openDropdownOnButton ? this.onDropdownClick : undefined}>
+ {this._props.button}
+ <div style={{ marginTop: '-8.5', position: 'relative' }} onPointerDown={!this._props.openDropdownOnButton ? this.onDropdownClick : undefined}>
<FontAwesomeIcon icon="caret-down" size="sm" />
</div>
</div>
) : (
<>
- {this.props.button}
+ {this._props.button}
<button className="dropdown-button antimodeMenu-button" key="antimodebutton" onPointerDown={this.onDropdownClick}>
<FontAwesomeIcon icon="caret-down" size="sm" />
</button>
</>
)}
- {this.showDropdown ? this.props.dropdownContent : null}
+ {this.showDropdown ? this._props.dropdownContent : null}
</div>
);
}