aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/nodes
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views/nodes')
-rw-r--r--src/client/views/nodes/CollectionFreeFormDocumentView.tsx2
-rw-r--r--src/client/views/nodes/DocumentView.tsx18
-rw-r--r--src/client/views/nodes/FieldView.tsx1
-rw-r--r--src/client/views/nodes/ImageBox.tsx8
-rw-r--r--src/client/views/nodes/KeyValueBox.tsx2
-rw-r--r--src/client/views/nodes/PDFBox.scss90
-rw-r--r--src/client/views/nodes/PDFBox.tsx14
-rw-r--r--src/client/views/nodes/formattedText/FormattedTextBox.scss9
-rw-r--r--src/client/views/nodes/formattedText/FormattedTextBox.tsx155
-rw-r--r--src/client/views/nodes/formattedText/RichTextMenu.tsx25
-rw-r--r--src/client/views/nodes/formattedText/RichTextRules.ts11
-rw-r--r--src/client/views/nodes/formattedText/nodes_rts.ts2
12 files changed, 172 insertions, 165 deletions
diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
index f934945a6..404d69730 100644
--- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
+++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
@@ -144,7 +144,7 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
boxShadow:
this.Opacity === 0 ? undefined : // if it's not visible, then no shadow
this.layoutDoc.z ? `#9c9396 ${StrCast(this.layoutDoc.boxShadow, "10px 10px 0.9vw")}` : // if it's a floating doc, give it a big shadow
- this.props.backgroundHalo?.() ? (`${this.props.backgroundColor?.(this.props.Document)} ${StrCast(this.layoutDoc.boxShadow, `0vw 0vw ${(this.layoutDoc.isBackground ? 100 : 50) / this.props.ContentScaling()}px`)}`) : // if it's just in a cluster, make the shadown roughly match the cluster border extent
+ this.props.backgroundHalo?.() && this.props.Document.type !== DocumentType.INK ? (`${this.props.backgroundColor?.(this.props.Document)} ${StrCast(this.layoutDoc.boxShadow, `0vw 0vw ${(this.layoutDoc.isBackground ? 100 : 50) / this.props.ContentScaling()}px`)}`) : // if it's just in a cluster, make the shadown roughly match the cluster border extent
this.layoutDoc.isBackground ? undefined : // if it's a background & has a cluster color, make the shadow spread really big
StrCast(this.layoutDoc.boxShadow, ""),
borderRadius: StrCast(Doc.Layout(this.layoutDoc).borderRounding),
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 3179409a8..707058aa7 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -325,20 +325,12 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
const alias = Doc.MakeAlias(this.props.Document);
DocUtils.makeCustomViewClicked(alias, undefined, "onClick");
this.props.addDocTab(alias, "onRight");
- // UndoManager.RunInBatch(() => Doc.makeCustomViewClicked(this.props.Document, undefined, "onClick"), "edit onClick");
- //ScriptBox.EditButtonScript("On Button Clicked ...", this.props.Document, "onClick", e.clientX, e.clientY), "on button click");
} else if (this.props.Document.links && this.Document.isLinkButton && !e.shiftKey && !e.ctrlKey) {
DocListCast(this.props.Document.links).length && this.followLinkClick(e.altKey, e.ctrlKey, e.shiftKey);
} else {
if ((this.props.Document.onDragStart || (this.props.Document.rootDocument)) && !(e.ctrlKey || e.button > 0)) { // onDragStart implies a button doc that we don't want to select when clicking. RootDocument & isTEmplaetForField implies we're clicking on part of a template instance and we want to select the whole template, not the part
stopPropagate = false; // don't stop propagation for field templates -- want the selection to propagate up to the root document of the template
} else {
- // if (this.props.Document.type === DocumentType.RTF) {
- // DocumentView._focusHack = this.props.ScreenToLocalTransform().transformPoint(e.clientX, e.clientY) || [0, 0];
- // DocumentView._focusHack = [DocumentView._focusHack[0] + NumCast(this.props.Document.x), DocumentView._focusHack[1] + NumCast(this.props.Document.y)];
-
- // this.props.focus(this.props.Document, false);
- // }
SelectionManager.SelectDoc(this, e.ctrlKey || e.shiftKey);
}
preventDefault = false;
@@ -578,7 +570,14 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
}
@undoBatch
- deleteClicked = (): void => { SelectionManager.DeselectAll(); this.props.removeDocument?.(this.props.Document); }
+ deleteClicked = (): void => {
+ if (Doc.UserDoc().activeWorkspace === this.props.Document) {
+ alert("Can't delete the active workspace");
+ } else {
+ SelectionManager.DeselectAll();
+ this.props.removeDocument?.(this.props.Document);
+ }
+ }
@undoBatch
@@ -1010,6 +1009,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
LayoutTemplate={this.props.LayoutTemplate}
makeLink={this.makeLink}
rootSelected={this.rootSelected}
+ backgroundHalo={this.props.backgroundHalo}
dontRegisterView={this.props.dontRegisterView}
fitToBox={this.props.fitToBox}
LibraryPath={this.props.LibraryPath}
diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx
index 305c04a90..c57738361 100644
--- a/src/client/views/nodes/FieldView.tsx
+++ b/src/client/views/nodes/FieldView.tsx
@@ -27,6 +27,7 @@ export interface FieldViewProps {
LibraryPath: Doc[];
onClick?: ScriptField;
dropAction: dropActionType;
+ backgroundHalo?: () => boolean;
docFilters: () => string[];
isSelected: (outsideReaction?: boolean) => boolean;
select: (isCtrlPressed: boolean) => void;
diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx
index 27b20db14..225d03104 100644
--- a/src/client/views/nodes/ImageBox.tsx
+++ b/src/client/views/nodes/ImageBox.tsx
@@ -397,15 +397,15 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps, ImageD
const shift = (rotation % 180) ? (nativeHeight - nativeWidth) * (1 - 1 / aspect) : 0;
this.resize(srcpath);
let transformOrigin = "center center";
- let transform = `translate(0%, 0%) rotate(${rotation}deg) scale(${aspect})`
+ let transform = `translate(0%, 0%) rotate(${rotation}deg) scale(${aspect})`;
if (rotation === 90 || rotation === -270) {
transformOrigin = "top left";
- transform = `translate(100%, 0%) rotate(${rotation}deg) scale(${aspect})`
+ transform = `translate(100%, 0%) rotate(${rotation}deg) scale(${aspect})`;
} else if (rotation === 180) {
- transform = `rotate(${rotation}deg) scale(${aspect})`
+ transform = `rotate(${rotation}deg) scale(${aspect})`;
} else if (rotation === 270 || rotation === -90) {
transformOrigin = "right top";
- transform = `translate(-100%, 0%) rotate(${rotation}deg) scale(${aspect})`
+ transform = `translate(-100%, 0%) rotate(${rotation}deg) scale(${aspect})`;
}
return <div className="imageBox-cont" key={this.layoutDoc[Id]} ref={this.createDropTarget}>
diff --git a/src/client/views/nodes/KeyValueBox.tsx b/src/client/views/nodes/KeyValueBox.tsx
index 4442ee2eb..d375466c9 100644
--- a/src/client/views/nodes/KeyValueBox.tsx
+++ b/src/client/views/nodes/KeyValueBox.tsx
@@ -147,7 +147,7 @@ export class KeyValueBox extends React.Component<FieldViewProps> {
<td className="keyValueBox-td-value" onClick={(e) => { this._valInput.current!.select(); e.stopPropagation(); }} style={{ width: `${this.splitPercentage}%` }}>
<input style={{ width: "100%" }} ref={this._valInput} type="text" placeholder="Value" onKeyDown={this.onEnterKey} />
</td>
- </tr>
+ </tr>;
}
@action
diff --git a/src/client/views/nodes/PDFBox.scss b/src/client/views/nodes/PDFBox.scss
index b19ddf1f5..974ddecdf 100644
--- a/src/client/views/nodes/PDFBox.scss
+++ b/src/client/views/nodes/PDFBox.scss
@@ -11,32 +11,53 @@
.pdfBox-ui {
position: absolute;
- width: 100%;
- height: 100%;
- z-index: 1;
- pointer-events: none;
+ width: 100%;
+ height: 100%;
+ z-index: 1;
+ pointer-events: none;
- .pdfBox-overlayButton {
- border-bottom-left-radius: 50%;
+ .pdfBox-pageNums {
display: flex;
- justify-content: space-evenly;
- align-items: center;
- height: 20px;
- background: none;
- padding: 0;
+ flex-direction: row;
+ height: 25px;
position: absolute;
- pointer-events: all;
-
- .pdfBox-overlayButton-arrow {
- width: 0;
- height: 0;
- border-top: 10px solid transparent;
- border-bottom: 10px solid transparent;
- border-right: 15px solid #121721;
- transition: all 0.5s;
+ left: 5px;
+ top: 5px;
+ .pdfBox-overlayButton-fwd,
+ .pdfBox-overlayButton-back {
+ background: #121721;
+ height: 25px;
+ width: 25px;
+ display: flex;
+ position: relative;
+ align-items: center;
+ justify-content: center;
+ border-radius: 3px;
+ pointer-events: all;
}
-
- .pdfBox-overlayButton-iconCont {
+ }
+
+ .pdfBox-overlayButton {
+ border-bottom-left-radius: 50%;
+ display: flex;
+ justify-content: space-evenly;
+ align-items: center;
+ height: 20px;
+ background: none;
+ padding: 0;
+ position: absolute;
+ pointer-events: all;
+
+ .pdfBox-overlayButton-arrow {
+ width: 0;
+ height: 0;
+ border-top: 10px solid transparent;
+ border-bottom: 10px solid transparent;
+ border-right: 15px solid #121721;
+ transition: all 0.5s;
+ }
+
+ .pdfBox-overlayButton-iconCont {
background: #121721;
height: 20px;
width: 25px;
@@ -49,29 +70,6 @@
}
}
- .pdfBox-overlayButton-fwd,
- .pdfBox-overlayButton-back {
- background: #121721;
- height: 25px;
- width: 25px;
- display: flex;
- position: relative;
- align-items: center;
- justify-content: center;
- border-radius: 3px;
- pointer-events: all;
- position: absolute;
- top: 5;
- }
-
- .pdfBox-overlayButton-fwd {
- left: 45;
- }
-
- .pdfBox-overlayButton-back {
- left: 25;
- }
-
.pdfBox-nextIcon,
.pdfBox-prevIcon {
background: #121721;
@@ -363,4 +361,4 @@
padding: 0px;
}
-} \ No newline at end of file
+}
diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx
index afd70bace..c1a0be9ea 100644
--- a/src/client/views/nodes/PDFBox.tsx
+++ b/src/client/views/nodes/PDFBox.tsx
@@ -147,6 +147,7 @@ export class PDFBox extends ViewBoxAnnotatableComponent<FieldViewProps, PdfDocum
</button>
</>;
const searchTitle = `${!this._searching ? "Open" : "Close"} Search Bar`;
+ const curPage = this.Document.curPage || 1;
return !this.active() ? (null) :
(<div className="pdfBox-ui" onKeyDown={e => e.keyCode === KeyCodes.BACKSPACE || e.keyCode === KeyCodes.DELETE ? e.stopPropagation() : true}
onPointerDown={e => e.stopPropagation()} style={{ display: this.active() ? "flex" : "none" }}>
@@ -170,11 +171,14 @@ export class PDFBox extends ViewBoxAnnotatableComponent<FieldViewProps, PdfDocum
<div className="pdfBox-overlayButton-iconCont" onPointerDown={(e) => e.stopPropagation()}>
<FontAwesomeIcon style={{ color: "white" }} icon={this._searching ? "times" : "search"} size="lg" /></div>
</button>
- <input value={`${(this.Document.curPage || 1)}`}
- onChange={e => this.gotoPage(Number(e.currentTarget.value))}
- style={{ left: 5, top: 5, height: "20px", width: "3ch", position: "absolute", pointerEvents: "all" }}
- onClick={action(() => this._pageControls = !this._pageControls)} />
- {this._pageControls ? pageBtns : (null)}
+
+ <div className="pdfBox-pageNums">
+ <input value={curPage}
+ onChange={e => this.gotoPage(Number(e.currentTarget.value))}
+ style={{ width: `${curPage > 99 ? 4 : 3}ch`, pointerEvents: "all" }}
+ onClick={action(() => this._pageControls = !this._pageControls)} />
+ {this._pageControls ? pageBtns : (null)}
+ </div>
<div className="pdfBox-settingsCont" key="settings" onPointerDown={(e) => e.stopPropagation()}>
<button className="pdfBox-settingsButton" onClick={action(() => this._flyout = !this._flyout)} title="Open Annotation Settings" >
<div className="pdfBox-settingsButton-arrow" style={{ transform: `scaleX(${this._flyout ? -1 : 1})` }} />
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.scss b/src/client/views/nodes/formattedText/FormattedTextBox.scss
index 17a1e83c1..5c084ae92 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.scss
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.scss
@@ -252,22 +252,23 @@ footnote::after {
.prosemirror-links {
display: none;
position: absolute;
- background-color: gray;
- padding-bottom: 10px;
- margin-top: 1em;
+ background-color: dimgray;
+ margin-top: 1.5em;
z-index: 1;
+ padding: 5;
+ border-radius: 2px;
}
.prosemirror-hrefoptions{
width:0px;
border:unset;
padding:0px;
-
}
.prosemirror-links a {
float: left;
color: white;
text-decoration: none;
+ border-radius: 3px;
}
.prosemirror-links a:hover {
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index e6cf2da07..a5a40a31f 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -58,7 +58,6 @@ import { FieldView, FieldViewProps } from "../FieldView";
import "./FormattedTextBox.scss";
import { FormattedTextBoxComment, formattedTextBoxCommentPlugin } from './FormattedTextBoxComment';
import React = require("react");
-import requestPromise = require('request-promise');
library.add(faEdit);
library.add(faSmile, faTextHeight, faUpload);
@@ -424,42 +423,66 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
specificContextMenu = (e: React.MouseEvent): void => {
const cm = ContextMenu.Instance;
- const funcs: ContextMenuProps[] = [];
- this.rootDoc.isTemplateDoc && funcs.push({ description: "Make Default Layout", event: async () => Doc.UserDoc().defaultTextLayout = new PrefetchProxy(this.rootDoc), icon: "eye" });
- !this.layoutDoc.isTemplateDoc && funcs.push({
- description: "Convert to use as a style", event: () => {
- this.rootDoc.isTemplateDoc = makeTemplate(this.rootDoc);
- Doc.AddDocToList(Cast(Doc.UserDoc()["template-notes"], Doc, null), "data", this.rootDoc);
- }, icon: "eye"
+ const appearance = ContextMenu.Instance.findByDescription("Appearance...");
+ const appearanceItems = appearance && "subitems" in appearance ? appearance.subitems : [];
+
+ const changeItems: ContextMenuProps[] = [];
+ const noteTypesDoc = Cast(Doc.UserDoc()["template-notes"], Doc, null);
+ DocListCast(noteTypesDoc?.data).forEach(note => {
+ changeItems.push({
+ description: StrCast(note.title), event: undoBatch(() => {
+ Doc.setNativeView(this.rootDoc);
+ DocUtils.makeCustomViewClicked(this.rootDoc, Docs.Create.TreeDocument, StrCast(note.title), note);
+ }), icon: "eye"
+ });
});
- this.layoutDoc.isTemplateDoc && funcs.push({
- description: "Make New Template", event: () => {
- const title = this.rootDoc.title as string;
- this.rootDoc.layout = (this.layoutDoc as Doc).layout as string;
- this.rootDoc.title = this.layoutDoc.isTemplateForField as string;
- this.rootDoc.isTemplateDoc = false;
- this.rootDoc.isTemplateForField = "";
- this.rootDoc.layoutKey = "layout";
- this.rootDoc.isTemplateDoc = makeTemplate(this.rootDoc, true, title);
- setTimeout(() => {
- this.rootDoc._width = this.layoutDoc._width || 300; // the width and height are stored on the template, since we're getting rid of the old template
- this.rootDoc._height = this.layoutDoc._height || 200; // we need to copy them over to the root. This should probably apply to all '_' fields
- this.rootDoc._backgroundColor = Cast(this.layoutDoc._backgroundColor, "string", null);
- }, 10);
+ changeItems.push({ description: "FreeForm", event: () => DocUtils.makeCustomViewClicked(this.rootDoc, Docs.Create.FreeformDocument, "freeform"), icon: "eye" });
+ appearanceItems.push({ description: "Change Perspective...", subitems: changeItems, icon: "external-link-alt" });
+ const uicontrols: ContextMenuProps[] = [];
+ uicontrols.push({ description: "Toggle Sidebar", event: () => this.layoutDoc._showSidebar = !this.layoutDoc._showSidebar, icon: "expand-arrows-alt" });
+ uicontrols.push({ description: "Toggle Dictation Icon", event: () => this.layoutDoc._showAudio = !this.layoutDoc._showAudio, icon: "expand-arrows-alt" });
+ uicontrols.push({ description: "Toggle Menubar", event: () => this.toggleMenubar(), icon: "expand-arrows-alt" });
+ !Doc.UserDoc().noviceMode && uicontrols.push({
+ description: "Broadcast Message", event: () => DocServer.GetRefField("rtfProto").then(proto =>
+ proto instanceof Doc && (proto.BROADCAST_MESSAGE = Cast(this.rootDoc[this.fieldKey], RichTextField)?.Text)), icon: "expand-arrows-alt"
+ });
+
+ appearanceItems.push({ description: "UI Controls...", subitems: uicontrols, icon: "asterisk" });
+ this.rootDoc.isTemplateDoc && appearanceItems.push({ description: "Make Default Layout", event: async () => Doc.UserDoc().defaultTextLayout = new PrefetchProxy(this.rootDoc), icon: "eye" });
+ Doc.UserDoc().defaultTextLayout && appearanceItems.push({ description: "Reset default note style", event: () => Doc.UserDoc().defaultTextLayout = undefined, icon: "eye" });
+ appearanceItems.push({
+ description: "Convert to be a template style", event: () => {
+ if (!this.layoutDoc.isTemplateDoc) {
+ const title = StrCast(this.rootDoc.title);
+ this.rootDoc.title = "text";
+ this.rootDoc.isTemplateDoc = makeTemplate(this.rootDoc, true, title);
+ } else {
+ const title = StrCast(this.rootDoc.title);
+ this.rootDoc.title = "text";
+ this.rootDoc.layout = (this.layoutDoc as Doc).layout as string;
+ this.rootDoc.title = this.layoutDoc.isTemplateForField as string;
+ this.rootDoc.isTemplateDoc = false;
+ this.rootDoc.isTemplateForField = "";
+ this.rootDoc.layoutKey = "layout";
+ this.rootDoc.isTemplateDoc = makeTemplate(this.rootDoc, true, title);
+ setTimeout(() => {
+ this.rootDoc._autoHeight = this.layoutDoc._autoHeight; // autoHeight, width and height
+ this.rootDoc._width = this.layoutDoc._width || 300; // are stored on the template, since we're getting rid of the old template
+ this.rootDoc._height = this.layoutDoc._height || 200; // we need to copy them over to the root. This should probably apply to all '_' fields
+ this.rootDoc._backgroundColor = Cast(this.layoutDoc._backgroundColor, "string", null);
+ }, 10);
+ }
Doc.AddDocToList(Cast(Doc.UserDoc()["template-notes"], Doc, null), "data", this.rootDoc);
}, icon: "eye"
});
+ !appearance && ContextMenu.Instance.addItem({ description: "Appearance...", subitems: appearanceItems, icon: "eye" });
+
+ const funcs: ContextMenuProps[] = [];
+
//funcs.push({ description: `${this.Document._autoHeight ? "Variable Height" : "Auto Height"}`, event: () => this.layoutDoc._autoHeight = !this.layoutDoc._autoHeight, icon: "plus" });
funcs.push({ description: (!this.layoutDoc._nativeWidth || !this.layoutDoc._nativeHeight ? "Freeze" : "Unfreeze") + " Aspect", event: this.toggleNativeDimensions, icon: "snowflake" });
funcs.push({ description: "Toggle Single Line", event: () => this.layoutDoc._singleLine = !this.layoutDoc._singleLine, icon: "expand-arrows-alt" });
- const uicontrols: ContextMenuProps[] = [];
- uicontrols.push({ description: "Toggle Sidebar", event: () => this.layoutDoc._showSidebar = !this.layoutDoc._showSidebar, icon: "expand-arrows-alt" });
- uicontrols.push({ description: "Toggle Dictation Icon", event: () => this.layoutDoc._showAudio = !this.layoutDoc._showAudio, icon: "expand-arrows-alt" });
- uicontrols.push({ description: "Toggle Menubar", event: () => this.toggleMenubar(), icon: "expand-arrows-alt" });
-
- funcs.push({ description: "UI Controls...", subitems: uicontrols, icon: "asterisk" });
-
const highlighting: ContextMenuProps[] = [];
["My Text", "Text from Others", "Todo Items", "Important Items", "Ignore Items", "Disagree Items", "By Recent Minute", "By Recent Hour"].forEach(option =>
highlighting.push({
@@ -476,21 +499,6 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
funcs.push({ description: "highlighting...", subitems: highlighting, icon: "hand-point-right" });
ContextMenu.Instance.addItem({ description: "Options...", subitems: funcs, icon: "asterisk" });
-
- const change = cm.findByDescription("Change Perspective...");
- const changeItems: ContextMenuProps[] = change && "subitems" in change ? change.subitems : [];
-
- const noteTypesDoc = Cast(Doc.UserDoc()["template-notes"], Doc, null);
- DocListCast(noteTypesDoc?.data).forEach(note => {
- changeItems.push({
- description: StrCast(note.title), event: undoBatch(() => {
- Doc.setNativeView(this.rootDoc);
- DocUtils.makeCustomViewClicked(this.rootDoc, Docs.Create.TreeDocument, StrCast(note.title), note);
- }), icon: "eye"
- });
- });
- changeItems.push({ description: "FreeForm", event: () => DocUtils.makeCustomViewClicked(this.rootDoc, Docs.Create.FreeformDocument, "freeform"), icon: "eye" });
- !change && cm.addItem({ description: "Change Perspective...", subitems: changeItems, icon: "external-link-alt" });
this._downX = this._downY = Number.NaN;
}
@@ -592,10 +600,10 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
};
}
- makeLinkToSelection(linkId: string, title: string, location: string, targetId: string) {
+ makeLinkToSelection(linkId: string, title: string, location: string, targetId: string, targetHref?: string) {
const state = this._editorView?.state;
if (state) {
- const href = Utils.prepend("/doc/" + linkId);
+ const href = targetHref ?? Utils.prepend("/doc/" + linkId);
const sel = state.selection;
const splitter = state.schema.marks.splitter.create({ id: Utils.GenerateGuid() });
let tr = state.tr.addMark(sel.from, sel.to, splitter);
@@ -603,7 +611,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
if (node.firstChild === null && node.marks.find((m: Mark) => m.type.name === schema.marks.splitter.name)) {
const allHrefs = [{ href, title, targetId, linkId }];
allHrefs.push(...(node.marks.find((m: Mark) => m.type.name === schema.marks.link.name)?.attrs.allHrefs ?? []));
- const link = state.schema.marks.link.create({ href, allHrefs, title, location, linkId, targetId });
+ const link = state.schema.marks.link.create({ allHrefs, title, location, linkId });
tr = tr.addMark(pos, pos + node.nodeSize, link);
}
});
@@ -930,6 +938,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
const { state: { tr }, dispatch } = this._editorView;
dispatch(tr.insertText(startupText));
}
+ (this._editorView as any).TextView = this;
}
const selectOnLoad = this.rootDoc[Id] === FormattedTextBox.SelectOnLoad;
@@ -1033,6 +1042,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
if (bounds && this.layoutDoc._chromeStatus !== "disabled") {
const x = Math.min(Math.max(bounds.left, 0), window.innerWidth - RichTextMenu.Instance.width);
let y = Math.min(Math.max(0, bounds.top - RichTextMenu.Instance.height - 50), window.innerHeight - RichTextMenu.Instance.height);
+ console.log("y = " + y + " hgt = " + RichTextMenu.Instance.height + " cords = " + coords.top);
if (coords && coords.left > x && coords.left < x + RichTextMenu.Instance.width && coords.top > y && coords.top < y + RichTextMenu.Instance.height + 50) {
y = Math.min(bounds.bottom, window.innerHeight - RichTextMenu.Instance.height);
}
@@ -1067,12 +1077,9 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
if ((e.nativeEvent as any).formattedHandled) { e.stopPropagation(); return; }
(e.nativeEvent as any).formattedHandled = true;
- if (Math.abs(e.clientX - this._downX) < 4 && Math.abs(e.clientX - this._downX) < 4) {
- this.props.select(e.ctrlKey);
- this.hitBulletTargets(e.clientX, e.clientY, e.shiftKey, false);
- }
if (this.props.isSelected(true)) { // if text box is selected, then it consumes all click events
e.stopPropagation();
+ this.hitBulletTargets(e.clientX, e.clientY, e.shiftKey, false);
}
}
@@ -1083,7 +1090,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
let olistPos = clickPos?.pos;
if (clickPos && olistPos && this.props.isSelected(true)) {
const clickNode = this._editorView?.state.doc.nodeAt(olistPos);
- let nodeBef = this._editorView?.state.doc.nodeAt(Math.max(0, olistPos - 1));
+ 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;
let $olistPos = this._editorView?.state.doc.resolve(olistPos);
let olistNode = (nodeBef !== null || clickNode?.type === this._editorView?.state.schema.nodes.list_item) && olistPos === clickPos?.pos ? clickNode : nodeBef;
@@ -1093,17 +1100,17 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
$olistPos = this._editorView?.state.doc.resolve(($olistPos as any).path[($olistPos as any).path.length - 4]);
}
}
- const listNode = this._editorView?.state.doc.nodeAt(clickPos.pos!);
+ const listNode = this._editorView?.state.doc.nodeAt(clickPos.pos);
if (olistNode && olistNode.type === this._editorView?.state.schema.nodes.ordered_list) {
if (!collapse) {
if (!highlightOnly) {
- this._editorView!.dispatch(this._editorView!.state.tr.setSelection(new NodeSelection($olistPos!)));
+ this._editorView.dispatch(this._editorView.state.tr.setSelection(new NodeSelection($olistPos!)));
}
addStyleSheetRule(FormattedTextBox._bulletStyleSheet, olistNode.attrs.mapStyle + olistNode.attrs.bulletStyle + ":hover:before", { background: "lightgray" });
} else if (listNode && listNode.type === this._editorView.state.schema.nodes.list_item) {
if (!highlightOnly) {
- this._editorView!.dispatch(this._editorView!.state.tr.setNodeMarkup(clickPos.pos!, listNode.type, { ...listNode.attrs, visibility: !listNode.attrs.visibility }));
- this._editorView!.dispatch(this._editorView!.state.tr.setSelection(TextSelection.create(this._editorView!.state.doc, clickPos.pos!)));
+ this._editorView.dispatch(this._editorView.state.tr.setNodeMarkup(clickPos.pos, listNode.type, { ...listNode.attrs, visibility: !listNode.attrs.visibility }));
+ this._editorView.dispatch(this._editorView.state.tr.setSelection(TextSelection.create(this._editorView.state.doc, clickPos.pos)));
}
addStyleSheetRule(FormattedTextBox._bulletStyleSheet, olistNode.attrs.mapStyle + olistNode.attrs.bulletStyle + ":hover:before", { background: "lightgray" });
}
@@ -1202,18 +1209,16 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
const nh = this.layoutDoc.isTemplateForField ? 0 : NumCast(this.dataDoc._nativeHeight, 0);
const dh = NumCast(this.rootDoc._height, 0);
const newHeight = Math.max(10, (nh ? dh / nh * scrollHeight : scrollHeight) + (this.props.ChromeHeight ? this.props.ChromeHeight() : 0));
- if (Math.abs(newHeight - dh) > 1) { // bcz: Argh! without this, we get into a React crash if the same document is opened in a freeform view and in the treeview. no idea why, but after dragging the freeform document, selecting it, and selecting text, it will compute to 1 pixel higher than the treeview which causes a cycle
- if (this.rootDoc !== this.layoutDoc.doc && !this.layoutDoc.resolvedDataDoc) {
- // if we have a template that hasn't been resolved yet, we can't set the height or we'd be setting it on the unresolved template. So set a timeout and hope its arrived...
- console.log("Delayed height adjustment...");
- setTimeout(() => {
- this.rootDoc._height = newHeight;
- this.dataDoc._nativeHeight = nh ? scrollHeight : undefined;
- }, 10);
- } else {
+ if (this.rootDoc !== this.layoutDoc.doc && !this.layoutDoc.resolvedDataDoc) {
+ // if we have a template that hasn't been resolved yet, we can't set the height or we'd be setting it on the unresolved template. So set a timeout and hope its arrived...
+ console.log("Delayed height adjustment...");
+ setTimeout(() => {
this.rootDoc._height = newHeight;
this.dataDoc._nativeHeight = nh ? scrollHeight : undefined;
- }
+ }, 10);
+ } else {
+ this.rootDoc._height = newHeight;
+ this.dataDoc._nativeHeight = nh ? scrollHeight : undefined;
}
}
}
@@ -1233,17 +1238,19 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
setTimeout(() => FormattedTextBoxComment.Hide(), 0);
}
const selPad = this.props.isSelected() ? -10 : 0;
- const selclass = this.props.isSelected() ? "-selected" : ""
+ const selclass = this.props.isSelected() ? "-selected" : "";
return (
- <div className={"formattedTextBox-cont"} style={{
- transform: `scale(${scale})`,
- transformOrigin: "top left",
- width: `${100 / scale}%`,
- height: `calc(${100 / scale}% - ${this.props.ChromeHeight?.() || 0}px)`,
- ...this.styleFromLayoutString(scale)
- }}>
+ <div className={"formattedTextBox-cont"}
+ style={{
+ transform: `scale(${scale})`,
+ transformOrigin: "top left",
+ width: `${100 / scale}%`,
+ height: `calc(${100 / scale}% - ${this.props.ChromeHeight?.() || 0}px)`,
+ ...this.styleFromLayoutString(scale)
+ }}>
<div className={`formattedTextBox-cont`} ref={this._ref}
style={{
+ overflow: this.layoutDoc._autoHeight ? "hidden" : undefined,
width: "100%",
height: this.props.height ? this.props.height : this.layoutDoc._autoHeight && this.props.renderDepth ? "max-content" : undefined,
background: Doc.UserDoc().renderStyle === "comic" ? "transparent" : this.props.background ? this.props.background : StrCast(this.layoutDoc[this.props.fieldKey + "-backgroundColor"], this.props.hideOnLeave ? "rgba(0,0,0 ,0.4)" : ""),
diff --git a/src/client/views/nodes/formattedText/RichTextMenu.tsx b/src/client/views/nodes/formattedText/RichTextMenu.tsx
index 1e14b8237..1a961ae21 100644
--- a/src/client/views/nodes/formattedText/RichTextMenu.tsx
+++ b/src/client/views/nodes/formattedText/RichTextMenu.tsx
@@ -12,7 +12,7 @@ import { faBold, faItalic, faChevronLeft, faUnderline, faStrikethrough, faSubscr
import { updateBullets } from "./ProsemirrorExampleTransfer";
import { FieldViewProps } from "../FieldView";
import { Cast, StrCast } from "../../../../fields/Types";
-import { FormattedTextBoxProps } from "./FormattedTextBox";
+import { FormattedTextBoxProps, FormattedTextBox } from "./FormattedTextBox";
import { unimplementedFunction, Utils } from "../../../../Utils";
import { wrapInList } from "prosemirror-schema-list";
import { PastelSchemaPalette, DarkPastelSchemaPalette } from '../../../../fields/SchemaHeaderField';
@@ -307,7 +307,6 @@ export default class RichTextMenu extends AntimodeMenu {
function onClick(e: React.PointerEvent) {
e.preventDefault();
e.stopPropagation();
- self.view && self.view.focus();
self.view && command && command(self.view.state, self.view.dispatch, self.view);
self.view && onclick && onclick(self.view.state, self.view.dispatch, self.view);
self.setActiveMarkButtons(self.getActiveMarksOnSelection());
@@ -427,7 +426,6 @@ export default class RichTextMenu extends AntimodeMenu {
function onBrushClick(e: React.PointerEvent) {
e.preventDefault();
e.stopPropagation();
- self.view && self.view.focus();
self.view && self.fillBrush(self.view.state, self.view.dispatch);
}
@@ -501,13 +499,11 @@ export default class RichTextMenu extends AntimodeMenu {
function onColorClick(e: React.PointerEvent) {
e.preventDefault();
e.stopPropagation();
- self.view && self.view.focus();
self.view && self.insertColor(self.activeFontColor, self.view.state, self.view.dispatch);
}
function changeColor(e: React.PointerEvent, color: string) {
e.preventDefault();
e.stopPropagation();
- self.view && self.view.focus();
self.setActiveColor(color);
self.view && self.insertColor(self.activeFontColor, self.view.state, self.view.dispatch);
}
@@ -554,13 +550,11 @@ export default class RichTextMenu extends AntimodeMenu {
function onHighlightClick(e: React.PointerEvent) {
e.preventDefault();
e.stopPropagation();
- self.view && self.view.focus();
self.view && self.insertHighlight(self.activeHighlightColor, self.view.state, self.view.dispatch);
}
function changeHighlight(e: React.PointerEvent, color: string) {
e.preventDefault();
e.stopPropagation();
- self.view && self.view.focus();
self.setActiveHighlight(color);
self.view && self.insertHighlight(self.activeHighlightColor, self.view.state, self.view.dispatch);
}
@@ -659,15 +653,8 @@ export default class RichTextMenu extends AntimodeMenu {
}
// TODO: should check for valid URL
- makeLinkToURL = (target: String, lcoation: string) => {
- if (!this.view) return;
-
- let node = this.view.state.selection.$from.nodeAfter;
- let link = this.view.state.schema.mark(this.view.state.schema.marks.link, { href: target, location: location });
- this.view.dispatch(this.view.state.tr.removeMark(this.view.state.selection.from, this.view.state.selection.to, this.view.state.schema.marks.link));
- this.view.dispatch(this.view.state.tr.addMark(this.view.state.selection.from, this.view.state.selection.to, link));
- node = this.view.state.selection.$from.nodeAfter;
- link = node && node.marks.find(m => m.type.name === "link");
+ makeLinkToURL = (target: string, lcoation: string) => {
+ ((this.view as any)?.TextView as FormattedTextBox).makeLinkToSelection("", target, "onRight", "", target);
}
deleteLink = () => {
@@ -760,13 +747,14 @@ export default class RichTextMenu extends AntimodeMenu {
this.collapsed = !this.collapsed;
setTimeout(() => {
const x = Math.min(this._left, window.innerWidth - RichTextMenu.Instance.width);
- RichTextMenu.Instance.jumpTo(x, this._top);
+ RichTextMenu.Instance.jumpTo(x, this._top, true);
}, 0);
}
render() {
const row1 = <div className="antimodeMenu-row" key="row1" style={{ display: this.collapsed ? "none" : undefined }}>{[
+ !this.collapsed ? this.getDragger() : (null),
this.createButton("bold", "Bold", this.boldActive, toggleMark(schema.marks.strong)),
this.createButton("italic", "Italic", this.italicsActive, toggleMark(schema.marks.em)),
this.createButton("underline", "Underline", this.underlineActive, toggleMark(schema.marks.underline)),
@@ -781,6 +769,7 @@ export default class RichTextMenu extends AntimodeMenu {
]}</div>;
const row2 = <div className="antimodeMenu-row row-2" key="antimodemenu row2">
+ {this.collapsed ? this.getDragger() : (null)}
<div key="row" style={{ display: this.collapsed ? "none" : undefined }}>
{[this.createMarksDropdown(this.activeFontSize, this.fontSizeOptions, "font size"),
this.createMarksDropdown(this.activeFontFamily, this.fontFamilyOptions, "font family"),
@@ -795,7 +784,6 @@ export default class RichTextMenu extends AntimodeMenu {
<button className="antimodeMenu-button" key="pin menu" title="Pin menu" onClick={this.toggleMenuPin} style={{ backgroundColor: this.Pinned ? "#121212" : "", display: this.collapsed ? "none" : undefined }}>
<FontAwesomeIcon icon="thumbtack" size="lg" style={{ transitionProperty: "transform", transitionDuration: "0.1s", transform: `rotate(${this.Pinned ? 45 : 0}deg)` }} />
</button>
- {this.getDragger()}
</div>
</div>;
@@ -840,7 +828,6 @@ class ButtonDropdown extends React.Component<ButtonDropdownProps> {
onDropdownClick = (e: React.PointerEvent) => {
e.preventDefault();
e.stopPropagation();
- this.props.view && this.props.view.focus();
this.toggleDropdown();
}
diff --git a/src/client/views/nodes/formattedText/RichTextRules.ts b/src/client/views/nodes/formattedText/RichTextRules.ts
index e442149d6..ba3230801 100644
--- a/src/client/views/nodes/formattedText/RichTextRules.ts
+++ b/src/client/views/nodes/formattedText/RichTextRules.ts
@@ -59,7 +59,16 @@ export class RichTextRules {
),
// * + - create bullet list
- wrappingInputRule(/^\s*([-+*])\s$/, schema.nodes.ordered_list),
+ wrappingInputRule(/^\s*([-+*])\s$/, schema.nodes.ordered_list,
+ // match => {
+ () => {
+ return ({ mapStyle: "bullet" });
+ // return ({ order: +match[1] })
+ },
+ (match: any, node: any) => {
+ return node.childCount + node.attrs.order === +match[1];
+ },
+ (type: any) => ({ type: type, attrs: { mapStyle: "bullet" } })),
// ``` create code block
textblockTypeInputRule(/^```$/, schema.nodes.code_block),
diff --git a/src/client/views/nodes/formattedText/nodes_rts.ts b/src/client/views/nodes/formattedText/nodes_rts.ts
index b37e61d3f..33ef67ff5 100644
--- a/src/client/views/nodes/formattedText/nodes_rts.ts
+++ b/src/client/views/nodes/formattedText/nodes_rts.ts
@@ -240,7 +240,7 @@ export const nodes: { [index: string]: NodeSpec } = {
},
{
style: 'list-style-type=disc', getAttrs(dom: any) {
- return { mapStyle: "bullet" }
+ return { mapStyle: "bullet" };
}
},
{