aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--deploy/index.html2
-rw-r--r--src/client/views/AntimodeMenu.tsx6
-rw-r--r--src/client/views/InkingStroke.tsx4
-rw-r--r--src/client/views/collections/CollectionViewChromes.tsx32
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx94
-rw-r--r--src/client/views/collections/collectionFreeForm/InkOptionsMenu.tsx1
-rw-r--r--src/client/views/collections/collectionFreeForm/MarqueeView.tsx1
-rw-r--r--src/client/views/nodes/CollectionFreeFormDocumentView.tsx2
-rw-r--r--src/client/views/nodes/DocumentView.tsx43
-rw-r--r--src/client/views/nodes/FieldView.tsx1
-rw-r--r--src/client/views/nodes/ScriptingBox.tsx16
-rw-r--r--src/client/views/nodes/WebBox.tsx7
-rw-r--r--src/client/views/nodes/formattedText/FormattedTextBox.scss9
-rw-r--r--src/client/views/nodes/formattedText/FormattedTextBox.tsx10
-rw-r--r--src/client/views/nodes/formattedText/RichTextMenu.tsx25
-rw-r--r--src/client/views/nodes/formattedText/RichTextRules.ts11
16 files changed, 147 insertions, 117 deletions
diff --git a/deploy/index.html b/deploy/index.html
index be0658da2..fdfd77cc2 100644
--- a/deploy/index.html
+++ b/deploy/index.html
@@ -9,7 +9,7 @@
</head>
<body>
- <script src="https://hypothes.is/embed.js" async></script>
+ <!-- <script src="https://hypothes.is/embed.js" async></script> -->
<div id="root"></div>
<script src="/bundle.js"></script>
</body>
diff --git a/src/client/views/AntimodeMenu.tsx b/src/client/views/AntimodeMenu.tsx
index 9a6121d20..2d26afcf6 100644
--- a/src/client/views/AntimodeMenu.tsx
+++ b/src/client/views/AntimodeMenu.tsx
@@ -131,15 +131,15 @@ export default abstract class AntimodeMenu extends React.Component {
}
protected getDragger = () => {
- return <div className="antimodeMenu-dragger" onPointerDown={this.dragStart} style={{ width: this.Pinned ? "20px" : "0px" }} />;
+ return <div className="antimodeMenu-dragger" onPointerDown={this.dragStart} style={{ width: "20px" }} />;
}
protected getElement(buttons: JSX.Element[]) {
return (
<div className="antimodeMenu-cont" onPointerLeave={this.pointerLeave} onPointerEnter={this.pointerEntered} ref={this._mainCont} onContextMenu={this.handleContextMenu}
style={{ left: this._left, top: this._top, opacity: this._opacity, transitionProperty: this._transitionProperty, transitionDuration: this._transitionDuration, transitionDelay: this._transitionDelay }}>
+ <div className="antimodeMenu-dragger" onPointerDown={this.dragStart} style={{ width: "20px" }} />
{buttons}
- <div className="antimodeMenu-dragger" onPointerDown={this.dragStart} style={{ width: this.Pinned ? "20px" : "0px" }} />
</div>
);
}
@@ -148,8 +148,8 @@ export default abstract class AntimodeMenu extends React.Component {
return (
<div className="antimodeMenu-cont with-rows" onPointerLeave={this.pointerLeave} onPointerEnter={this.pointerEntered} ref={this._mainCont} onContextMenu={this.handleContextMenu}
style={{ left: this._left, top: this._top, opacity: this._opacity, transitionProperty: this._transitionProperty, transitionDuration: this._transitionDuration, transitionDelay: this._transitionDelay, height: "auto" }}>
+ {hasDragger ? <div className="antimodeMenu-dragger" onPointerDown={this.dragStart} style={{ width: "20px" }} /> : (null)}
{rows}
- {hasDragger ? <div className="antimodeMenu-dragger" onPointerDown={this.dragStart} style={{ width: this.Pinned ? "20px" : "0px" }} /> : <></>}
</div>
);
}
diff --git a/src/client/views/InkingStroke.tsx b/src/client/views/InkingStroke.tsx
index 7e3bd1c17..cdabd213b 100644
--- a/src/client/views/InkingStroke.tsx
+++ b/src/client/views/InkingStroke.tsx
@@ -4,7 +4,7 @@ import { observer } from "mobx-react";
import { documentSchema } from "../../fields/documentSchemas";
import { InkData, InkField, InkTool } from "../../fields/InkField";
import { makeInterface } from "../../fields/Schema";
-import { Cast, StrCast } from "../../fields/Types";
+import { Cast, StrCast, BoolCast } from "../../fields/Types";
import { TraceMobx } from "../../fields/util";
import { CognitiveServices } from "../cognitive_services/CognitiveServices";
import { InteractionUtils } from "../util/InteractionUtils";
@@ -54,7 +54,7 @@ export class InkingStroke extends ViewBoxBaseComponent<FieldViewProps, InkDocume
const scaleY = (this.props.PanelHeight() - strokeWidth) / (height - strokeWidth);
const strokeColor = StrCast(this.layoutDoc.color, ActiveInkColor());
const points = InteractionUtils.CreatePolyline(data, left, top, strokeColor, strokeWidth, strokeWidth,
- StrCast(this.layoutDoc.strokeBezier, ActiveInkBezierApprox()), scaleX, scaleY, "", "none", this.props.isSelected() && strokeWidth <= 5);
+ StrCast(this.layoutDoc.strokeBezier, ActiveInkBezierApprox()), scaleX, scaleY, "", "none", (this.props.isSelected() || BoolCast(this.props.backgroundHalo?.())) && strokeWidth <= 5);
const hpoints = InteractionUtils.CreatePolyline(data, left, top,
this.props.isSelected() && strokeWidth > 5 ? strokeColor : "transparent", strokeWidth, (strokeWidth + 15),
StrCast(this.layoutDoc.strokeBezier, ActiveInkBezierApprox()), scaleX, scaleY, "", this.props.active() ? "visiblestroke" : "none", false);
diff --git a/src/client/views/collections/CollectionViewChromes.tsx b/src/client/views/collections/CollectionViewChromes.tsx
index 52fb63386..ac7136d4d 100644
--- a/src/client/views/collections/CollectionViewChromes.tsx
+++ b/src/client/views/collections/CollectionViewChromes.tsx
@@ -40,28 +40,41 @@ export class CollectionViewBaseChrome extends React.Component<CollectionViewChro
_templateCommand = {
params: ["target", "source"], title: "=> item view",
script: "this.target.childLayout = getDocTemplate(this.source?.[0])",
- immediate: (source: Doc[]) => this.target.childLayout = Doc.getDocTemplate(source?.[0]),
+ immediate: undoBatch((source: Doc[]) => source.length && (this.target.childLayout = Doc.getDocTemplate(source?.[0]))),
initialize: emptyFunction,
};
_narrativeCommand = {
params: ["target", "source"], title: "=> child click view",
script: "this.target.childClickedOpenTemplateView = getDocTemplate(this.source?.[0])",
- immediate: (source: Doc[]) => this.target.childClickedOpenTemplateView = Doc.getDocTemplate(source?.[0]),
+ immediate: undoBatch((source: Doc[]) => source.length && (this.target.childClickedOpenTemplateView = Doc.getDocTemplate(source?.[0]))),
initialize: emptyFunction,
};
_contentCommand = {
- params: ["target", "source"], title: "=> content",
+ params: ["target", "source"], title: "=> clear content",
script: "getProto(this.target).data = copyField(this.source);",
- immediate: (source: Doc[]) => Doc.GetProto(this.target).data = new List<Doc>(source), // Doc.aliasDocs(source),
+ immediate: undoBatch((source: Doc[]) => Doc.GetProto(this.target).data = new List<Doc>(source)), // Doc.aliasDocs(source),
initialize: emptyFunction,
};
_viewCommand = {
- params: ["target"], title: "=> saved view",
+ params: ["target"], title: "=> reset view",
script: "this.target._panX = this.restoredPanX; this.target._panY = this.restoredPanY; this.target.scale = this.restoredScale;",
- immediate: (source: Doc[]) => { this.target._panX = 0; this.target._panY = 0; this.target.scale = 1; },
+ immediate: undoBatch((source: Doc[]) => { this.target._panX = 0; this.target._panY = 0; this.target.scale = 1; }),
initialize: (button: Doc) => { button.restoredPanX = this.target._panX; button.restoredPanY = this.target._panY; button.restoredScale = this.target.scale; },
};
- _freeform_commands = [this._contentCommand, this._templateCommand, this._narrativeCommand, this._viewCommand];
+ _clusterCommand = {
+ params: ["target"], title: "=> fit content",
+ script: "this.target._fitToBox = !this.target._fitToBox;",
+ immediate: undoBatch((source: Doc[]) => this.target._fitToBox = !this.target._fitToBox),
+ initialize: emptyFunction
+ };
+ _fitContentCommand = {
+ params: ["target"], title: "=> toggle clusters",
+ script: "this.target.useClusters = !this.target.useClusters;",
+ immediate: undoBatch((source: Doc[]) => this.target.useClusters = !this.target.useClusters),
+ initialize: emptyFunction
+ };
+
+ _freeform_commands = [this._viewCommand, this._fitContentCommand, this._clusterCommand, this._contentCommand, this._templateCommand, this._narrativeCommand];
_stacking_commands = [this._contentCommand, this._templateCommand];
_masonry_commands = [this._contentCommand, this._templateCommand];
_schema_commands = [this._templateCommand, this._narrativeCommand];
@@ -84,6 +97,7 @@ export class CollectionViewBaseChrome extends React.Component<CollectionViewChro
@observable private _currentKey: string = "";
componentDidMount = action(() => {
+ this._currentKey = this._currentKey || (this._buttonizableCommands.length ? this._buttonizableCommands[0]?.title : "");
// chrome status is one of disabled, collapsed, or visible. this determines initial state from document
switch (this.props.CollectionView.props.Document._chromeStatus) {
case "disabled":
@@ -248,7 +262,9 @@ export class CollectionViewBaseChrome extends React.Component<CollectionViewChro
DragManager.StartButtonDrag([this._commandRef.current!], c.script, c.title,
{ target: this.props.CollectionView.props.Document }, c.params, c.initialize, e.clientX, e.clientY));
return true;
- }, emptyFunction, emptyFunction);
+ }, emptyFunction, () => {
+ this._buttonizableCommands.filter(c => c.title === this._currentKey).map(c => c.immediate([]));
+ });
}
@computed get templateChrome() {
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 960b6efef..3a8778c14 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -46,6 +46,7 @@ import { CollectionViewType } from "../CollectionView";
import { Timeline } from "../../animationtimeline/Timeline";
import { SnappingManager } from "../../../util/SnappingManager";
import { ActiveInkColor, ActiveInkWidth, ActiveInkBezierApprox } from "../../InkingStroke";
+import { DocumentType } from "../../../documents/DocumentTypes";
library.add(faEye as any, faTable, faPaintBrush, faExpandArrowsAlt, faCompressArrowsAlt, faCompass, faUpload, faBraille, faChalkboard, faFileUpload);
@@ -240,11 +241,18 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
@action
internalLinkDrop(e: Event, de: DragManager.DropEvent, linkDragData: DragManager.LinkDragData, xp: number, yp: number) {
if (linkDragData.linkSourceDocument === this.props.Document || this.props.Document.annotationOn) return false;
- const source = Docs.Create.TextDocument("", { _width: 200, _height: 75, x: xp, y: yp, title: "dropped annotation" });
- this.props.addDocument(source);
- linkDragData.linkDocument = DocUtils.MakeLink({ doc: source }, { doc: linkDragData.linkSourceDocument }, "doc annotation"); // TODODO this is where in text links get passed
- e.stopPropagation();
- return true;
+ if (!linkDragData.linkSourceDocument.context || StrCast(Cast(linkDragData.linkSourceDocument.context, Doc, null)?.type) === DocumentType.COL) {
+ // const source = Docs.Create.TextDocument("", { _width: 200, _height: 75, x: xp, y: yp, title: "dropped annotation" });
+ // this.props.addDocument(source);
+ // linkDragData.linkDocument = DocUtils.MakeLink({ doc: source }, { doc: linkDragData.linkSourceDocument }, "doc annotation"); // TODODO this is where in text links get passed
+ return false;
+ } else {
+ const source = Docs.Create.TextDocument("", { _width: 200, _height: 75, x: xp, y: yp, title: "dropped annotation" });
+ this.props.addDocument(source);
+ linkDragData.linkDocument = DocUtils.MakeLink({ doc: source }, { doc: linkDragData.linkSourceDocument }, "doc annotation"); // TODODO this is where in text links get passed
+ e.stopPropagation();
+ return true;
+ }
}
@action
@@ -1128,6 +1136,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
this.props.Document[this.scaleFieldKey] = Math.max(1, NumCast(this.props.Document[this.scaleFieldKey]));
}
+ this.Document.useClusters && !this._clusterSets.length && this.childDocs.length && this.updateClusters(true);
return elements;
}
@@ -1197,59 +1206,58 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
onContextMenu = (e: React.MouseEvent) => {
if (this.props.annotationsKey) return;
- !this.props.isAnnotationOverlay && ContextMenu.Instance.addItem({
- description: (this._timelineVisible ? "Close" : "Open") + " Animation Timeline", event: action(() => {
- this._timelineVisible = !this._timelineVisible;
- }), icon: this._timelineVisible ? faEyeSlash : faEye
- });
-
const appearance = ContextMenu.Instance.findByDescription("Appearance...");
const appearanceItems = appearance && "subitems" in appearance ? appearance.subitems : [];
appearanceItems.push({ description: "reset view", event: () => { this.props.Document._panX = this.props.Document._panY = 0; this.props.Document[this.scaleFieldKey] = 1; }, icon: "compress-arrows-alt" });
appearanceItems.push({ description: `${this.fitToContent ? "Unset" : "Set"} Fit To Container`, event: () => this.Document._fitToBox = !this.fitToContent, icon: !this.fitToContent ? "expand-arrows-alt" : "compress-arrows-alt" });
appearanceItems.push({ description: `${this.Document.useClusters ? "Uncluster" : "Use Clusters"}`, event: () => this.updateClusters(!this.Document.useClusters), icon: "braille" });
- appearanceItems.push({ description: "Use Background Color as Default", event: () => Cast(Doc.UserDoc().emptyCollection, Doc, null)!._backgroundColor = StrCast(this.layoutDoc._backgroundColor), icon: "palette" });
+ appearanceItems.push({ description: "Use Background Color as Default", event: () => Cast(Doc.UserDoc().emptyCollection, Doc, null)._backgroundColor = StrCast(this.layoutDoc._backgroundColor), icon: "palette" });
!appearance && ContextMenu.Instance.addItem({ description: "Appearance...", subitems: appearanceItems, icon: "eye" });
const options = ContextMenu.Instance.findByDescription("Options...");
const optionItems = options && "subitems" in options ? options.subitems : [];
- optionItems.push({ description: "toggle snap line display", event: () => Doc.UserDoc().showSnapLines = !Doc.UserDoc().showSnapLines, icon: "compress-arrows-alt" });
- !Doc.UserDoc().noviceMode && optionItems.push({ description: (!this.layoutDoc._nativeWidth || !this.layoutDoc._nativeHeight ? "Freeze" : "Unfreeze") + " Aspect", event: this.toggleNativeDimensions, icon: "snowflake" });
- this.props.ContainingCollectionView && optionItems.push({ description: "Promote Collection", event: this.promoteCollection, icon: "table" });
+ !this.props.isAnnotationOverlay &&
+ optionItems.push({ description: (this.showTimeline ? "Close" : "Open") + " Animation Timeline", event: action(() => this.showTimeline = !this.showTimeline), icon: faEye });
+ this.props.ContainingCollectionView &&
+ optionItems.push({ description: "Promote Collection", event: this.promoteCollection, icon: "table" });
+ optionItems.push({ description: (Doc.UserDoc().showSnapLines ? "Hide" : "Show") + " snap lines", event: () => Doc.UserDoc().showSnapLines = !Doc.UserDoc().showSnapLines, icon: "compress-arrows-alt" });
optionItems.push({ description: this.layoutDoc._lockedTransform ? "Unlock Transform" : "Lock Transform", event: this.toggleLockTransform, icon: this.layoutDoc._lockedTransform ? "unlock" : "lock" });
optionItems.push({ description: "Arrange contents in grid", event: this.layoutDocsInGrid, icon: "table" });
- !Doc.UserDoc().noviceMode && optionItems.push({
- description: "Import document", icon: "upload", event: ({ x, y }) => {
- const input = document.createElement("input");
- input.type = "file";
- input.accept = ".zip";
- input.onchange = async _e => {
- const upload = Utils.prepend("/uploadDoc");
- const formData = new FormData();
- const file = input.files && input.files[0];
- if (file) {
- formData.append('file', file);
- formData.append('remap', "true");
- const response = await fetch(upload, { method: "POST", body: formData });
- const json = await response.json();
- if (json !== "error") {
- const doc = await DocServer.GetRefField(json);
- if (doc instanceof Doc) {
- const [xx, yy] = this.props.ScreenToLocalTransform().transformPoint(x, y);
- doc.x = xx, doc.y = yy;
- this.props.addDocument?.(doc);
+ if (!Doc.UserDoc().noviceMode) {
+ optionItems.push({ description: (!this.layoutDoc._nativeWidth || !this.layoutDoc._nativeHeight ? "Freeze" : "Unfreeze") + " Aspect", event: this.toggleNativeDimensions, icon: "snowflake" });
+ optionItems.push({ description: `${this.Document._LODdisable ? "Enable LOD" : "Disable LOD"}`, event: () => this.Document._LODdisable = !this.Document._LODdisable, icon: "table" });
+ optionItems.push({
+ description: "Import document", icon: "upload", event: ({ x, y }) => {
+ const input = document.createElement("input");
+ input.type = "file";
+ input.accept = ".zip";
+ input.onchange = async _e => {
+ const upload = Utils.prepend("/uploadDoc");
+ const formData = new FormData();
+ const file = input.files && input.files[0];
+ if (file) {
+ formData.append('file', file);
+ formData.append('remap', "true");
+ const response = await fetch(upload, { method: "POST", body: formData });
+ const json = await response.json();
+ if (json !== "error") {
+ const doc = await DocServer.GetRefField(json);
+ if (doc instanceof Doc) {
+ const [xx, yy] = this.props.ScreenToLocalTransform().transformPoint(x, y);
+ doc.x = xx, doc.y = yy;
+ this.props.addDocument?.(doc);
+ }
}
}
- }
- };
- input.click();
- }
- });
- !Doc.UserDoc().noviceMode && optionItems.push({ description: `${this.Document._LODdisable ? "Enable LOD" : "Disable LOD"}`, event: () => this.Document._LODdisable = !this.Document._LODdisable, icon: "table" });
+ };
+ input.click();
+ }
+ });
+ }
!options && ContextMenu.Instance.addItem({ description: "Options...", subitems: optionItems, icon: "eye" });
}
- @observable _timelineVisible = false;
+ @observable showTimeline = false;
intersectRect(r1: { left: number, top: number, width: number, height: number },
r2: { left: number, top: number, width: number, height: number }) {
@@ -1350,7 +1358,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
zoomScaling={this.zoomScaling} panX={this.panX} panY={this.panY}>
{this.children}
</CollectionFreeFormViewPannableContents>
- {this._timelineVisible ? <Timeline ref={this._timelineRef} {...this.props} /> : (null)}
+ {this.showTimeline ? <Timeline ref={this._timelineRef} {...this.props} /> : (null)}
</MarqueeView>;
}
diff --git a/src/client/views/collections/collectionFreeForm/InkOptionsMenu.tsx b/src/client/views/collections/collectionFreeForm/InkOptionsMenu.tsx
index ae82c6a65..4fac87ca5 100644
--- a/src/client/views/collections/collectionFreeForm/InkOptionsMenu.tsx
+++ b/src/client/views/collections/collectionFreeForm/InkOptionsMenu.tsx
@@ -118,7 +118,6 @@ export default class InkOptionsMenu extends AntimodeMenu {
render() {
const buttons = [
- <button className="antimodeMenu-button" title="Drag" key="drag" onPointerDown={e => this.dragStart(e)}> ✜ </button>,
...this.shapeButtons,
this.bezierButton,
this.widthPicker,
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index 23efeec8d..1bc7c6fb5 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -741,7 +741,6 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque
return <div className="marqueeView"
style={{ overflow: StrCast(this.props.Document._overflow), cursor: MarqueeView.DragMarquee && this ? "crosshair" : "hand" }}
onDragOver={e => e.preventDefault()}
- onPaste={this.paste}
onScroll={(e) => e.currentTarget.scrollTop = e.currentTarget.scrollLeft = 0} onClick={this.onClick} onPointerDown={this.onPointerDown}>
{this._visible ? this.marqueeDiv : null}
{this.props.children}
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 71cb18e08..6f3c46be6 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -121,7 +121,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
@computed get freezeDimensions() { return this.props.FreezeDimensions; }
@computed get nativeWidth() { return NumCast(this.layoutDoc._nativeWidth, this.props.NativeWidth() || (this.freezeDimensions ? this.layoutDoc[WidthSym]() : 0)); }
@computed get nativeHeight() { return NumCast(this.layoutDoc._nativeHeight, this.props.NativeHeight() || (this.freezeDimensions ? this.layoutDoc[HeightSym]() : 0)); }
- @computed get onClickHandler() { return this.props.onClick || Cast(this.layoutDoc.onClick, ScriptField, null) || this.Document.onClick; }
+ @computed get onClickHandler() { return this.props.onClick || Cast(this.layoutDoc.onClick, ScriptField, null); }
@computed get onDoubleClickHandler() { return this.props.onDoubleClick || Cast(this.layoutDoc.onDoubleClick, ScriptField, null) || this.Document.onDoubleClick; }
@computed get onPointerDownHandler() { return this.props.onPointerDown ? this.props.onPointerDown : this.Document.onPointerDown; }
@computed get onPointerUpHandler() { return this.props.onPointerUp ? this.props.onPointerUp : this.Document.onPointerUp; }
@@ -233,10 +233,10 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
dragData.offset = this.props.ScreenToLocalTransform().scale(this.props.ContentScaling()).transformDirection(x - left, y - top);
dragData.dropAction = dropAction;
dragData.removeDocument = this.props.removeDocument;
- dragData.moveDocument = this.props.moveDocument;// this.Document.onDragStart ? undefined : this.props.moveDocument;
+ dragData.moveDocument = this.props.moveDocument;// this.layoutDoc.onDragStart ? undefined : this.props.moveDocument;
dragData.dragDivName = this.props.dragDivName;
dragData.treeViewId = this.props.treeViewId;
- DragManager.StartDocumentDrag([this._mainCont.current], dragData, x, y, { hideSource: !dropAction && !this.Document.onDragStart });
+ DragManager.StartDocumentDrag([this._mainCont.current], dragData, x, y, { hideSource: !dropAction && !this.layoutDoc.onDragStart });
}
}
@@ -326,7 +326,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
} 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
+ if ((this.layoutDoc.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 {
SelectionManager.SelectDoc(this, e.ctrlKey || e.shiftKey);
@@ -372,7 +372,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
this._downX = touch.clientX;
this._downY = touch.clientY;
if (!e.nativeEvent.cancelBubble) {
- if ((this.active || this.Document.onDragStart || this.Document.onClick) && !e.ctrlKey && !this.Document.lockedPosition && !this.Document.inOverlay) e.stopPropagation();
+ if ((this.active || this.layoutDoc.onDragStart || this.layoutDoc.onClick) && !e.ctrlKey && !this.layoutDoc.lockedPosition && !this.layoutDoc.inOverlay) e.stopPropagation();
this.removeMoveListeners();
this.addMoveListeners();
this.removeEndListeners();
@@ -387,11 +387,11 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
if (e.cancelBubble && this.active) {
this.removeMoveListeners();
}
- else if (!e.cancelBubble && (SelectionManager.IsSelected(this, true) || this.props.parentActive(true) || this.Document.onDragStart || this.Document.onClick) && !this.Document.lockedPosition && !this.Document.inOverlay) {
+ else if (!e.cancelBubble && (SelectionManager.IsSelected(this, true) || this.props.parentActive(true) || this.layoutDoc.onDragStart || this.layoutDoc.onClick) && !this.layoutDoc.lockedPosition && !this.layoutDoc.inOverlay) {
const touch = me.touchEvent.changedTouches.item(0);
if (touch && (Math.abs(this._downX - touch.clientX) > 3 || Math.abs(this._downY - touch.clientY) > 3)) {
- if (!e.altKey && (!this.topMost || this.Document.onDragStart || this.Document.onClick)) {
+ if (!e.altKey && (!this.topMost || this.layoutDoc.onDragStart || this.layoutDoc.onClick)) {
this.cleanUpInteractions();
this.startDragging(this._downX, this._downY, this.Document.dropAction ? this.Document.dropAction as any : e.ctrlKey || e.altKey ? "alias" : undefined);
}
@@ -504,15 +504,15 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
}
this._downX = e.clientX;
this._downY = e.clientY;
- if ((!e.nativeEvent.cancelBubble || this.onClickHandler || this.Document.onDragStart) &&
+ if ((!e.nativeEvent.cancelBubble || this.onClickHandler || this.layoutDoc.onDragStart) &&
// if this is part of a template, let the event go up to the tempalte root unless right/ctrl clicking
!((this.props.Document.rootDocument) && !(e.ctrlKey || e.button > 0))) {
- if ((this.active || this.Document.onDragStart) &&
+ if ((this.active || this.layoutDoc.onDragStart) &&
!e.ctrlKey &&
(e.button === 0 || InteractionUtils.IsType(e, InteractionUtils.TOUCHTYPE)) &&
- !this.Document.inOverlay) {
+ !this.layoutDoc.inOverlay) {
e.stopPropagation();
- if (SelectionManager.IsSelected(this, true) && this.props.Document._viewType !== CollectionViewType.Docking) e.preventDefault(); // goldenlayout needs to be able to move its tabs, so can't preventDefault for it
+ if (SelectionManager.IsSelected(this, true) && this.layoutDoc._viewType !== CollectionViewType.Docking) e.preventDefault(); // goldenlayout needs to be able to move its tabs, so can't preventDefault for it
}
document.removeEventListener("pointermove", this.onPointerMove);
document.removeEventListener("pointerup", this.onPointerUp);
@@ -530,9 +530,9 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
if (e.cancelBubble && this.active) {
document.removeEventListener("pointermove", this.onPointerMove); // stop listening to pointerMove if something else has stopPropagated it (e.g., the MarqueeView)
}
- else if (!e.cancelBubble && (SelectionManager.IsSelected(this, true) || this.props.parentActive(true) || this.Document.onDragStart) && !this.Document.lockedPosition && !this.Document.inOverlay) {
+ else if (!e.cancelBubble && (SelectionManager.IsSelected(this, true) || this.props.parentActive(true) || this.layoutDoc.onDragStart) && !this.layoutDoc.lockedPosition && !this.layoutDoc.inOverlay) {
if (Math.abs(this._downX - e.clientX) > 3 || Math.abs(this._downY - e.clientY) > 3) {
- if (!e.altKey && (!this.topMost || this.Document.onDragStart || this.onClickHandler) && (e.buttons === 1 || InteractionUtils.IsType(e, InteractionUtils.TOUCHTYPE))) {
+ if (!e.altKey && (!this.topMost || this.layoutDoc.onDragStart || this.onClickHandler) && (e.buttons === 1 || InteractionUtils.IsType(e, InteractionUtils.TOUCHTYPE))) {
document.removeEventListener("pointermove", this.onPointerMove);
document.removeEventListener("pointerup", this.onPointerUp);
this.startDragging(this._downX, this._downY, ((e.ctrlKey || e.altKey) && "alias") || (this.props.dropAction || this.Document.dropAction || undefined) as dropActionType);
@@ -580,10 +580,10 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
@undoBatch
toggleLinkButtonBehavior = (): void => {
- if (this.Document.isLinkButton || this.Document.onClick || this.Document.ignoreClick) {
+ if (this.Document.isLinkButton || this.layoutDoc.onClick || this.Document.ignoreClick) {
this.Document.isLinkButton = false;
this.Document.ignoreClick = false;
- this.Document.onClick = undefined;
+ this.layoutDoc.onClick = undefined;
} else {
this.Document.isLinkButton = true;
this.Document.followLinkZoom = false;
@@ -738,19 +738,19 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
const existingOnClick = cm.findByDescription("OnClick...");
const onClicks: ContextMenuProps[] = existingOnClick && "subitems" in existingOnClick ? existingOnClick.subitems : [];
onClicks.push({ description: "Enter Portal", event: this.makeIntoPortal, icon: "window-restore" });
- onClicks.push({ description: "Toggle Detail", event: () => this.Document.onClick = ScriptField.MakeScript(`toggleDetail(self, "${this.props.Document.layoutKey}")`), icon: "window-restore" });
+ onClicks.push({ description: "Toggle Detail", event: () => this.layoutDoc.onClick = ScriptField.MakeScript(`toggleDetail(self, "${this.Document.layoutKey}")`), icon: "window-restore" });
onClicks.push({ description: this.Document.ignoreClick ? "Select" : "Do Nothing", event: () => this.Document.ignoreClick = !this.Document.ignoreClick, icon: this.Document.ignoreClick ? "unlock" : "lock" });
onClicks.push({ description: this.Document.isLinkButton ? "Remove Follow Behavior" : "Follow Link in Place", event: this.toggleFollowInPlace, icon: "concierge-bell" });
onClicks.push({ description: this.Document.isLinkButton ? "Remove Follow Behavior" : "Follow Link on Right", event: this.toggleFollowOnRight, icon: "concierge-bell" });
- onClicks.push({ description: this.Document.isLinkButton || this.Document.onClick ? "Remove Click Behavior" : "Follow Link", event: this.toggleLinkButtonBehavior, icon: "concierge-bell" });
+ onClicks.push({ description: this.Document.isLinkButton || this.layoutDoc.onClick ? "Remove Click Behavior" : "Follow Link", event: this.toggleLinkButtonBehavior, icon: "concierge-bell" });
onClicks.push({ description: "Edit onClick Script", event: () => UndoManager.RunInBatch(() => DocUtils.makeCustomViewClicked(this.props.Document, undefined, "onClick"), "edit onClick"), icon: "edit" });
!existingOnClick && cm.addItem({ description: "OnClick...", subitems: onClicks, icon: "hand-point-right" });
const funcs: ContextMenuProps[] = [];
- if (this.Document.onDragStart) {
- funcs.push({ description: "Drag an Alias", icon: "edit", event: () => this.Document.dragFactory && (this.Document.onDragStart = ScriptField.MakeFunction('getAlias(this.dragFactory)')) });
- funcs.push({ description: "Drag a Copy", icon: "edit", event: () => this.Document.dragFactory && (this.Document.onDragStart = ScriptField.MakeFunction('getCopy(this.dragFactory, true)')) });
- funcs.push({ description: "Drag Document", icon: "edit", event: () => this.Document.onDragStart = undefined });
+ if (this.layoutDoc.onDragStart) {
+ funcs.push({ description: "Drag an Alias", icon: "edit", event: () => this.Document.dragFactory && (this.layoutDoc.onDragStart = ScriptField.MakeFunction('getAlias(this.dragFactory)')) });
+ funcs.push({ description: "Drag a Copy", icon: "edit", event: () => this.Document.dragFactory && (this.layoutDoc.onDragStart = ScriptField.MakeFunction('getCopy(this.dragFactory, true)')) });
+ funcs.push({ description: "Drag Document", icon: "edit", event: () => this.layoutDoc.onDragStart = undefined });
cm.addItem({ description: "OnDrag...", subitems: funcs, icon: "asterisk" });
}
@@ -1007,6 +1007,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/ScriptingBox.tsx b/src/client/views/nodes/ScriptingBox.tsx
index 8912b113c..04ac34cc2 100644
--- a/src/client/views/nodes/ScriptingBox.tsx
+++ b/src/client/views/nodes/ScriptingBox.tsx
@@ -62,6 +62,10 @@ export class ScriptingBox extends ViewBoxAnnotatableComponent<FieldViewProps, Sc
@observable private _scriptSuggestedParams: any = "";
@observable private _scriptParamsText: any = "";
+ constructor(props: any) {
+ super(props);
+ }
+
// vars included in fields that store parameters types and names and the script itself
@computed({ keepAlive: true }) get paramsNames() { return this.compileParams.map(p => p.split(":")[0].trim()); }
@computed({ keepAlive: true }) get paramsTypes() { return this.compileParams.map(p => p.split(":")[1].trim()); }
@@ -135,9 +139,6 @@ export class ScriptingBox extends ViewBoxAnnotatableComponent<FieldViewProps, Sc
@action
onFinish = () => {
this.rootDoc.layoutKey = "layout";
- this.rootDoc._height = 50;
- this.rootDoc._width = 100;
- this.dataDoc.documentText = this.rawScript;
}
// displays error message
@@ -158,8 +159,7 @@ export class ScriptingBox extends ViewBoxAnnotatableComponent<FieldViewProps, Sc
params,
typecheck: false
});
- this.dataDoc.documentText = this.rawScript;
- this.dataDoc.data = result.compiled ? new ScriptField(result) : undefined;
+ this.dataDoc[this.fieldKey] = result.compiled ? new ScriptField(result) : undefined;
this.onError(result.compiled ? undefined : result.errors);
return result.compiled;
}
@@ -171,7 +171,7 @@ export class ScriptingBox extends ViewBoxAnnotatableComponent<FieldViewProps, Sc
const bindings: { [name: string]: any } = {};
this.paramsNames.forEach(key => bindings[key] = this.dataDoc[key]);
// binds vars so user doesnt have to refer to everything as self.<var>
- ScriptCast(this.dataDoc.data, null)?.script.run({ self: this.rootDoc, this: this.layoutDoc, ...bindings }, this.onError);
+ ScriptCast(this.dataDoc[this.fieldKey], null)?.script.run({ self: this.rootDoc, this: this.layoutDoc, ...bindings }, this.onError);
}
}
@@ -589,7 +589,8 @@ export class ScriptingBox extends ViewBoxAnnotatableComponent<FieldViewProps, Sc
}
// inputs for scripting div (script box, params box, and params column)
- @computed({ keepAlive: true }) get renderScriptingInputs() {
+ @computed get renderScriptingInputs() {
+ TraceMobx();
// should there be a border? style={{ borderStyle: "groove", borderBlockWidth: "1px" }}
// params box on bottom
@@ -673,6 +674,7 @@ export class ScriptingBox extends ViewBoxAnnotatableComponent<FieldViewProps, Sc
// renders script UI if _applied = false and params UI if _applied = true
render() {
+ TraceMobx();
return (
<div className={`scriptingBox`} onContextMenu={this.specificContextMenu}
onPointerUp={!this._function ? this.suggestionPos : undefined}>
diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx
index b726a6df9..71e8d2778 100644
--- a/src/client/views/nodes/WebBox.tsx
+++ b/src/client/views/nodes/WebBox.tsx
@@ -41,7 +41,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps, WebDocum
@observable private _url: string = "hello";
@observable private _pressX: number = 0;
@observable private _pressY: number = 0;
-
+ private _keyInput = React.createRef<HTMLInputElement>();
private _longPressSecondsHack?: NodeJS.Timeout;
private _outerRef = React.createRef<HTMLDivElement>();
private _iframeRef = React.createRef<HTMLIFrameElement>();
@@ -237,6 +237,11 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps, WebDocum
onDragOver={this.onUrlDragover}
onChange={this.onURLChange}
onKeyDown={this.onValueKeyDown}
+ onClick={(e) => {
+ this._keyInput.current!.select();
+ e.stopPropagation();
+ }}
+ ref={this._keyInput}
/>
<div style={{
display: "flex",
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.scss b/src/client/views/nodes/formattedText/FormattedTextBox.scss
index 348ed4ba5..ccdf41233 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.scss
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.scss
@@ -251,22 +251,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 5e0585169..3ee5603e5 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -452,7 +452,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
appearanceItems.push({
description: "Convert to be a template style", event: () => {
if (!this.layoutDoc.isTemplateDoc) {
- const title = StrCast(this.rootDoc.title)
+ const title = StrCast(this.rootDoc.title);
this.rootDoc.title = "text";
this.rootDoc.isTemplateDoc = makeTemplate(this.rootDoc, true, title);
} else {
@@ -599,10 +599,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);
@@ -610,7 +610,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);
}
});
@@ -937,6 +937,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;
@@ -1040,6 +1041,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);
}
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),