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/AudioBox.tsx12
-rw-r--r--src/client/views/nodes/CollectionFreeFormDocumentView.tsx1
-rw-r--r--src/client/views/nodes/DocumentContentsView.tsx6
-rw-r--r--src/client/views/nodes/DocumentView.tsx82
-rw-r--r--src/client/views/nodes/KeyValueBox.tsx2
-rw-r--r--src/client/views/nodes/KeyValuePair.tsx2
-rw-r--r--src/client/views/nodes/LabelBox.tsx2
-rw-r--r--src/client/views/nodes/LinkAnchorBox.tsx2
-rw-r--r--src/client/views/nodes/LinkDocPreview.tsx2
-rw-r--r--src/client/views/nodes/ScriptingBox.tsx16
-rw-r--r--src/client/views/nodes/WebBox.tsx8
-rw-r--r--src/client/views/nodes/button/ButtonScripts.ts16
-rw-r--r--src/client/views/nodes/button/FontIconBox.scss20
-rw-r--r--src/client/views/nodes/button/FontIconBox.tsx273
-rw-r--r--src/client/views/nodes/formattedText/DashDocCommentView.tsx16
-rw-r--r--src/client/views/nodes/formattedText/DashDocView.tsx16
-rw-r--r--src/client/views/nodes/formattedText/DashFieldView.tsx8
-rw-r--r--src/client/views/nodes/formattedText/FormattedTextBox.tsx27
-rw-r--r--src/client/views/nodes/formattedText/RichTextRules.ts26
-rw-r--r--src/client/views/nodes/formattedText/nodes_rts.ts8
-rw-r--r--src/client/views/nodes/trails/PresBox.tsx7
21 files changed, 217 insertions, 335 deletions
diff --git a/src/client/views/nodes/AudioBox.tsx b/src/client/views/nodes/AudioBox.tsx
index 5e4315833..384975b45 100644
--- a/src/client/views/nodes/AudioBox.tsx
+++ b/src/client/views/nodes/AudioBox.tsx
@@ -446,7 +446,7 @@ export class AudioBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
@action
timelineWhenChildContentsActiveChanged = (isActive: boolean) => this.props.whenChildContentsActiveChanged((this._isAnyChildContentActive = isActive));
- timelineScreenToLocal = () => this.props.ScreenToLocalTransform().translate(0, -AudioBox.bottomControlsHeight);
+ timelineScreenToLocal = () => this.props.ScreenToLocalTransform().translate(0, -AudioBox.topControlsHeight);
setPlayheadTime = (time: number) => (this._ele!.currentTime = this.layoutDoc._currentTimecode = time);
@@ -635,15 +635,11 @@ export class AudioBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
step="0.1"
min="1"
max="5"
- value={this.timeline?._zoomFactor}
+ value={this.timeline?._zoomFactor ?? 1}
className="toolbar-slider"
id="zoom-slider"
- onPointerDown={(e: React.PointerEvent) => {
- e.stopPropagation();
- }}
- onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
- this.zoom(Number(e.target.value));
- }}
+ onPointerDown={(e: React.PointerEvent) => e.stopPropagation()}
+ onChange={(e: React.ChangeEvent<HTMLInputElement>) => this.zoom(Number(e.target.value))}
/>
</div>
)}
diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
index 901415d1e..9bdb2cee7 100644
--- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
+++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
@@ -7,7 +7,6 @@ import { ComputedField } from '../../../fields/ScriptField';
import { Cast, NumCast, StrCast } from '../../../fields/Types';
import { TraceMobx } from '../../../fields/util';
import { numberRange } from '../../../Utils';
-import { DocumentType } from '../../documents/DocumentTypes';
import { DocumentManager } from '../../util/DocumentManager';
import { SelectionManager } from '../../util/SelectionManager';
import { Transform } from '../../util/Transform';
diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx
index 105f7e151..c21bc9754 100644
--- a/src/client/views/nodes/DocumentContentsView.tsx
+++ b/src/client/views/nodes/DocumentContentsView.tsx
@@ -1,4 +1,4 @@
-import { computed, trace } from 'mobx';
+import { computed } from 'mobx';
import { observer } from 'mobx-react';
import { AclPrivate, Doc, Opt } from '../../../fields/Doc';
import { ScriptField } from '../../../fields/ScriptField';
@@ -9,6 +9,7 @@ import { DirectoryImportBox } from '../../util/Import & Export/DirectoryImportBo
import { CollectionDockingView } from '../collections/CollectionDockingView';
import { CollectionFreeFormView } from '../collections/collectionFreeForm/CollectionFreeFormView';
import { CollectionSchemaView } from '../collections/collectionSchema/CollectionSchemaView';
+import { SchemaRowBox } from '../collections/collectionSchema/SchemaRowBox';
import { CollectionView } from '../collections/CollectionView';
import { InkingStroke } from '../InkingStroke';
import { PresElementBox } from '../nodes/trails/PresElementBox';
@@ -31,6 +32,7 @@ import { KeyValueBox } from './KeyValueBox';
import { LabelBox } from './LabelBox';
import { LinkAnchorBox } from './LinkAnchorBox';
import { LinkBox } from './LinkBox';
+import { LoadingBox } from './LoadingBox';
import { MapBox } from './MapBox/MapBox';
import { PDFBox } from './PDFBox';
import { RecordingBox } from './RecordingBox';
@@ -42,8 +44,6 @@ import { VideoBox } from './VideoBox';
import { WebBox } from './WebBox';
import React = require('react');
import XRegExp = require('xregexp');
-import { LoadingBox } from './LoadingBox';
-import { SchemaRowBox } from '../collections/collectionSchema/SchemaRowBox';
const JsxParser = require('react-jsx-parser').default; //TODO Why does this need to be imported like this?
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index fcfcaaeda..f34ac2b44 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -54,6 +54,7 @@ import { ScriptingBox } from './ScriptingBox';
import { PresEffect, PresEffectDirection } from './trails';
import { PinProps, PresBox } from './trails/PresBox';
import React = require('react');
+import { KeyValueBox } from './KeyValueBox';
const { Howl } = require('howler');
interface Window {
@@ -80,6 +81,7 @@ export enum OpenWhere {
replaceLeft = 'replace:left',
inParent = 'inParent',
inParentFromScreen = 'inParentFromScreen',
+ overlay = 'overlay',
}
export enum OpenWhereMod {
none = '',
@@ -87,6 +89,7 @@ export enum OpenWhereMod {
right = 'right',
top = 'top',
bottom = 'bottom',
+ rightKeyValue = 'rightKeyValue',
}
export interface DocFocusOptions {
@@ -94,6 +97,7 @@ export interface DocFocusOptions {
willZoomCentered?: boolean; // determines whether to zoom in on target document
zoomScale?: number; // percent of containing frame to zoom into document
zoomTime?: number;
+ didMove?: boolean; // whether a document was changed during the showDocument process
docTransform?: Transform; // when a document can't be panned and zoomed within its own container (say a group), then we need to continue to move up the render hierarchy to find something that can pan and zoom. when this happens the docTransform must accumulate all the transforms of each level of the hierarchy
instant?: boolean; // whether focus should happen instantly (as opposed to smooth zoom)
preview?: boolean; // whether changes should be previewed by the componentView or written to the document
@@ -160,6 +164,7 @@ export interface DocumentViewSharedProps {
childHideResizeHandles?: () => boolean;
dataTransition?: string; // specifies animation transition - used by collectionPile and potentially other layout engines when changing the size of documents so that the change won't be abrupt
styleProvider: Opt<StyleProviderFunc>;
+ setTitleFocus?: () => void;
focus: DocFocusFunc;
fitWidth?: (doc: Doc) => boolean | undefined;
docFilters: () => string[];
@@ -313,8 +318,8 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
@computed get titleHeight() {
return this.props?.styleProvider?.(this.layoutDoc, this.props, StyleProp.TitleHeight) || 0;
}
- @computed get pointerEvents() {
- return this.props.styleProvider?.(this.Document, this.props, StyleProp.PointerEvents + (this.props.isSelected() ? ':selected' : ''));
+ @computed get pointerEvents(): 'none' | 'all' | 'visiblePainted' | undefined {
+ return this.onClickHandler ? 'all' : this.props.styleProvider?.(this.Document, this.props, StyleProp.PointerEvents + (this.props.isSelected() ? ':selected' : ''));
}
@computed get finalLayoutKey() {
return StrCast(this.Document.layoutKey, 'layout');
@@ -326,7 +331,8 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
return this.props.NativeHeight();
}
@computed get onClickHandler() {
- return this.props.onClick?.() ?? this.props.onBrowseClick?.() ?? Cast(this.Document.onClick, ScriptField, Cast(this.layoutDoc.onClick, ScriptField, null));
+ const noClick = this.rootSelected() || this.props.isSelected() || this._componentView?.isAnyChildContentActive?.();
+ return noClick ? undefined : this.props.onClick?.() ?? this.props.onBrowseClick?.() ?? Cast(this.Document.onClick, ScriptField, Cast(this.layoutDoc.onClick, ScriptField, null));
}
@computed get onDoubleClickHandler() {
return this.props.onDoubleClick?.() ?? Cast(this.layoutDoc.onDoubleClick, ScriptField, null) ?? this.Document.onDoubleClick;
@@ -538,18 +544,11 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
.ScreenToLocalTransform()
.scale(this.NativeDimScaling)
.transformDirection(x - left, y - top);
- // dragData.offset[0] = Math.min(this.rootDoc[WidthSym](), dragData.offset[0]); // bcz: this was breaking dragging rotated objects since the offset may be out of bounds with regard to the unrotated document
- // dragData.offset[1] = Math.min(this.rootDoc[HeightSym](), dragData.offset[1]);
dragData.dropAction = dropAction;
dragData.treeViewDoc = this.props.treeViewDoc;
dragData.removeDocument = this.props.removeDocument;
dragData.moveDocument = this.props.moveDocument;
dragData.canEmbed = this.props.canEmbedOnDrag;
- //dragData.dimSource :
- // dragEffects field, set dim
- // add kv pairs to a doc, swap properties with the node while dragging, and then swap when dropping
- // add a dragEffects prop to DocumentView as a function that sets up. Each view has its own prop, when you start dragging:
- // in Draganager, figure out which doc(s) you're dragging and change what opacity function returns
const ffview = this.props.CollectionFreeFormDocumentView?.().props.CollectionFreeFormView;
ffview && runInAction(() => (ffview.ChildDrag = this.props.DocumentView()));
DragManager.StartDocumentDrag([this._mainCont.current], dragData, x, y, { hideSource: hideSource || (!dropAction && !this.layoutDoc.onDragStart && !this.props.dontHideOnDrag) }, () =>
@@ -559,22 +558,6 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
}
}
- onKeyDown = (e: React.KeyboardEvent) => {
- if (e.altKey) {
- e.stopPropagation();
- e.preventDefault();
- if (e.key === '†' || e.key === 't') {
- if (!StrCast(this.layoutDoc._showTitle)) this.layoutDoc._showTitle = 'title';
- if (!this._titleRef.current) setTimeout(() => this._titleRef.current?.setIsFocused(true));
- else if (!this._titleRef.current.setIsFocused(true)) {
- // if focus didn't change, focus on interior text...
- this._titleRef.current?.setIsFocused(false);
- this._componentView?.setFocus?.();
- }
- }
- }
- };
-
defaultRestoreTargetView = (docView: DocumentView, anchor: Doc, focusSpeed: number, options: DocFocusOptions) => {
const targetMatch =
Doc.AreProtosEqual(anchor, this.rootDoc) || // anchor is this document, so anchor's properties apply to this document
@@ -584,6 +567,12 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
return targetMatch && PresBox.restoreTargetDocView(docView, anchor, focusSpeed) ? focusSpeed : undefined;
};
+ // switches text input focus to the title bar of the document (and displays the title bar if it hadn't been)
+ setTitleFocus = () => {
+ if (!StrCast(this.layoutDoc._showTitle)) this.layoutDoc._showTitle = 'title';
+ setTimeout(() => this._titleRef.current?.setIsFocused(true)); // use timeout in case title wasn't shown to allow re-render so that titleref will be defined
+ };
+
onClick = action((e: React.MouseEvent | React.PointerEvent) => {
if (!this.Document.ignoreClick && this.props.renderDepth >= 0 && Math.abs(e.clientX - this._downX) < Utils.DRAG_THRESHOLD && Math.abs(e.clientY - this._downY) < Utils.DRAG_THRESHOLD) {
let stopPropagate = true;
@@ -613,6 +602,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
altKey,
shiftKey,
ctrlKey,
+ value: undefined,
},
console.log
);
@@ -627,7 +617,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
// bcz: hack? don't execute script if you're clicking on a scripting box itself
const { clientX, clientY, shiftKey, altKey, metaKey } = e;
const func = () =>
- this.onClickHandler.script.run(
+ this.onClickHandler?.script.run(
{
this: this.layoutDoc,
self: this.rootDoc,
@@ -655,7 +645,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
} else clickFunc();
} else if (!this._longPress && this.allLinks.length && this.Document.type !== DocumentType.LINK && !isScriptBox() && this.Document.isLinkButton && !e.shiftKey && !e.ctrlKey) {
SelectionManager.DeselectAll();
- this.allLinks.length && LinkFollower.FollowLink(undefined, this.props.Document, this.props, e.altKey);
+ this.allLinks.length && LinkFollower.FollowLink(undefined, this.props.Document, e.altKey);
} else {
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 & isTemplateForField implies we're clicking on part of a template instance and we want to select the whole template, not the part
@@ -990,7 +980,6 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
const more = cm.findByDescription('More...');
const moreItems = more && 'subitems' in more ? more.subitems : [];
if (!Doc.IsSystem(this.rootDoc)) {
- (this.rootDoc._viewType !== CollectionViewType.Docking || !Doc.noviceMode) && moreItems.push({ description: 'Share', event: () => SharingManager.Instance.open(this.props.DocumentView()), icon: 'users' });
if (!Doc.noviceMode) {
moreItems.push({ description: 'Make View of Metadata Field', event: () => Doc.MakeMetadataFieldTemplate(this.props.Document, this.props.DataDoc), icon: 'concierge-bell' });
moreItems.push({ description: `${this.Document._chromeHidden ? 'Show' : 'Hide'} Chrome`, event: () => (this.Document._chromeHidden = !this.Document._chromeHidden), icon: 'project-diagram' });
@@ -1002,6 +991,9 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
}
moreItems.push({ description: 'Copy ID', event: () => Utils.CopyText(Doc.globalServerPath(this.props.Document)), icon: 'fingerprint' });
}
+ moreItems.push({ description: 'Export collection', icon: 'download', event: async () => Doc.Zip(this.props.Document) });
+
+ (this.rootDoc._viewType !== CollectionViewType.Docking || !Doc.noviceMode) && moreItems.push({ description: 'Share', event: () => SharingManager.Instance.open(this.props.DocumentView()), icon: 'users' });
}
if (this.props.removeDocument && !Doc.IsSystem(this.rootDoc) && Doc.ActiveDashboard !== this.props.Document) {
@@ -1012,7 +1004,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
}
const help = cm.findByDescription('Help...');
const helpItems: ContextMenuProps[] = help && 'subitems' in help ? help.subitems : [];
- helpItems.push({ description: 'Show Metadata', event: () => this.props.addDocTab(Docs.Create.KVPDocument(this.props.Document, { _width: 300, _height: 300 }), OpenWhere.addRight), icon: 'layer-group' });
+ helpItems.push({ description: 'Show Metadata', event: () => this.props.addDocTab(this.props.Document, (OpenWhere.addRight.toString() + 'KeyValue') as OpenWhere), icon: 'layer-group' });
!Doc.noviceMode && helpItems.push({ description: 'Text Shortcuts Ctrl+/', event: () => this.props.addDocTab(Docs.Create.PdfDocument('/assets/cheat-sheet.pdf', { _width: 300, _height: 300 }), OpenWhere.addRight), icon: 'keyboard' });
!Doc.noviceMode && helpItems.push({ description: 'Print Document in Console', event: () => console.log(this.props.Document), icon: 'hand-point-right' });
!Doc.noviceMode && helpItems.push({ description: 'Print DataDoc in Console', event: () => console.log(this.props.Document[DataSym]), icon: 'hand-point-right' });
@@ -1078,7 +1070,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
rootSelected = (outsideReaction?: boolean) => this.props.isSelected(outsideReaction) || (this.props.Document.rootDocument && this.props.rootSelected?.(outsideReaction)) || false;
panelHeight = () => this.props.PanelHeight() - this.headerMargin;
screenToLocal = () => this.props.ScreenToLocalTransform().translate(0, -this.headerMargin);
- onClickFunc = () => this.onClickHandler;
+ onClickFunc = () => this.onClickHandler as any as ScriptField; // bcz: typing HACK. check and fix.
setHeight = (height: number) => (this.layoutDoc._height = height);
setContentView = action((view: { getAnchor?: (addAsAnnotation: boolean) => Doc; forward?: () => boolean; back?: () => boolean }) => (this._componentView = view));
isContentActive = (outsideReaction?: boolean) => {
@@ -1129,22 +1121,14 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
</Tooltip>
);
}
+ contentPointerEvents = () => (this.onClickHandler ? 'none' : this.pointerEvents);
@computed get contents() {
TraceMobx();
return (
<div
className="documentView-contentsView"
style={{
- pointerEvents:
- this.opacity === 0
- ? 'none'
- : (this.props.pointerEvents?.() as any) ?? this.rootDoc.layoutKey === 'layout_icon'
- ? 'none'
- : (this.props.contentPointerEvents as any)
- ? (this.props.contentPointerEvents as any)
- : this.rootDoc.type !== DocumentType.INK && this.isContentActive()
- ? 'all'
- : 'none',
+ pointerEvents: this.pointerEvents === 'visiblePainted' ? 'none' : this.pointerEvents,
height: this.headerMargin ? `calc(100% - ${this.headerMargin}px)` : undefined,
}}>
{!this._retryThumb || !this.thumbShown() ? null : (
@@ -1165,7 +1149,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
<DocumentContentsView
key={1}
{...this.props}
- pointerEvents={this.opacity === 0 ? returnNone : this.props.pointerEvents}
+ pointerEvents={this.contentPointerEvents}
docViewPath={this.props.viewPath}
thumbShown={this.thumbShown}
isHovering={this.props.isHovering}
@@ -1177,7 +1161,8 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
ScreenToLocalTransform={this.screenToLocal}
rootSelected={this.rootSelected}
onClick={this.onClickFunc}
- focus={emptyFunction}
+ focus={this.props.focus}
+ setTitleFocus={this.setTitleFocus}
layoutKey={this.finalLayoutKey}
/>
{this.layoutDoc.hideAllLinks ? null : this.allLinkEndpoints}
@@ -1495,7 +1480,6 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
className={`${DocumentView.ROOT_DIV} docView-hack`}
ref={this._mainCont}
onContextMenu={this.onContextMenu}
- onKeyDown={this.onKeyDown}
onPointerDown={this.onPointerDown}
onClick={this.onClick}
onPointerEnter={e => (!SnappingManager.GetIsDragging() || DragManager.CanEmbed) && Doc.BrushDoc(this.props.Document)}
@@ -1504,7 +1488,7 @@ export class DocumentViewInternal extends DocComponent<DocumentViewInternalProps
style={{
display: this.hidden ? 'inline' : undefined,
borderRadius: this.borderRounding,
- pointerEvents: this.pointerEvents,
+ pointerEvents: this.pointerEvents === 'visiblePainted' ? 'none' : this.pointerEvents,
}}>
{!borderPath.path ? (
animRenderDoc
@@ -1581,8 +1565,8 @@ export class DocumentView extends React.Component<DocumentViewProps> {
}
public static showBackLinks(linkSource: Doc) {
- const docid = Doc.CurrentUserEmail + Doc.GetProto(linkSource)[Id] + '-pivotish';
- DocServer.GetRefField(docid).then(docx => {
+ const docId = Doc.CurrentUserEmail + Doc.GetProto(linkSource)[Id] + '-pivotish';
+ DocServer.GetRefField(docId).then(docx => {
const rootAlias = () => {
const rootAlias = Doc.MakeAlias(linkSource);
rootAlias.x = rootAlias.y = 0;
@@ -1595,7 +1579,7 @@ export class DocumentView extends React.Component<DocumentViewProps> {
/*rootAlias()*/
],
{ title: linkSource.title + '-pivot', _width: 500, _height: 500 },
- docid
+ docId
);
linkCollection.linkSource = linkSource;
if (!linkCollection.reactionScript) linkCollection.reactionScript = ScriptField.MakeScript('updateLinkCollection(self)');
@@ -1857,7 +1841,7 @@ export class DocumentView extends React.Component<DocumentViewProps> {
transform: isButton ? undefined : `translate(${this.centeringX}px, ${this.centeringY}px)`,
width: isButton ? '100%' : xshift ?? `${(100 * (this.props.PanelWidth() - this.Xshift * 2)) / this.props.PanelWidth()}%`,
height:
- isButton || this.props.forceAutoHeight
+ isButton || this.props.LayoutTemplateString?.includes(KeyValueBox.name) || this.props.forceAutoHeight
? undefined
: yshift ?? (this.fitWidth ? `${this.panelHeight}px` : `${(((100 * this.effectiveNativeHeight) / this.effectiveNativeWidth) * this.props.PanelWidth()) / this.props.PanelHeight()}%`),
}}>
diff --git a/src/client/views/nodes/KeyValueBox.tsx b/src/client/views/nodes/KeyValueBox.tsx
index 60417430f..9f9d93a82 100644
--- a/src/client/views/nodes/KeyValueBox.tsx
+++ b/src/client/views/nodes/KeyValueBox.tsx
@@ -45,7 +45,7 @@ export class KeyValueBox extends React.Component<FieldViewProps> {
return NumCast(this.props.Document.schemaSplitPercentage, 50);
}
get fieldDocToLayout() {
- return this.props.fieldKey ? Cast(this.props.Document[this.props.fieldKey], Doc, null) : this.props.Document;
+ return this.props.fieldKey ? DocCast(this.props.Document[this.props.fieldKey], DocCast(this.props.Document)) : this.props.Document;
}
@action
diff --git a/src/client/views/nodes/KeyValuePair.tsx b/src/client/views/nodes/KeyValuePair.tsx
index e74ef4a39..c4adc7f1a 100644
--- a/src/client/views/nodes/KeyValuePair.tsx
+++ b/src/client/views/nodes/KeyValuePair.tsx
@@ -48,7 +48,7 @@ export class KeyValuePair extends React.Component<KeyValuePairProps> {
if (value instanceof Doc) {
e.stopPropagation();
e.preventDefault();
- ContextMenu.Instance.addItem({ description: 'Open Fields', event: () => this.props.addDocTab(Docs.Create.KVPDocument(value, { _width: 300, _height: 300 }), OpenWhere.addRight), icon: 'layer-group' });
+ ContextMenu.Instance.addItem({ description: 'Open Fields', event: () => this.props.addDocTab(value, ((OpenWhere.addRight as string) + 'KeyValue') as OpenWhere), icon: 'layer-group' });
ContextMenu.Instance.displayMenu(e.clientX, e.clientY);
}
};
diff --git a/src/client/views/nodes/LabelBox.tsx b/src/client/views/nodes/LabelBox.tsx
index 33fab6873..6e0b4be37 100644
--- a/src/client/views/nodes/LabelBox.tsx
+++ b/src/client/views/nodes/LabelBox.tsx
@@ -79,7 +79,7 @@ export class LabelBox extends ViewBoxBaseComponent<FieldViewProps & LabelBoxProp
@observable _mouseOver = false;
@computed get hoverColor() {
- return this._mouseOver ? StrCast(this.layoutDoc._hoverBackgroundColor) : 'unset';
+ return this._mouseOver ? StrCast(this.layoutDoc._hoverBackgroundColor) : this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor);
}
fitTextToBox = (r: any): any => {
diff --git a/src/client/views/nodes/LinkAnchorBox.tsx b/src/client/views/nodes/LinkAnchorBox.tsx
index 1b37dc7ab..e12548f18 100644
--- a/src/client/views/nodes/LinkAnchorBox.tsx
+++ b/src/client/views/nodes/LinkAnchorBox.tsx
@@ -39,7 +39,7 @@ export class LinkAnchorBox extends ViewBoxBaseComponent<FieldViewProps>() {
this.onPointerMove,
emptyFunction,
(e, doubleTap) => {
- if (doubleTap) LinkFollower.FollowLink(this.rootDoc, anchorContainerDoc, this.props, false);
+ if (doubleTap) LinkFollower.FollowLink(this.rootDoc, anchorContainerDoc, false);
else this.props.select(false);
},
false
diff --git a/src/client/views/nodes/LinkDocPreview.tsx b/src/client/views/nodes/LinkDocPreview.tsx
index 16b352e4f..fcc5b6975 100644
--- a/src/client/views/nodes/LinkDocPreview.tsx
+++ b/src/client/views/nodes/LinkDocPreview.tsx
@@ -171,7 +171,7 @@ export class LinkDocPreview extends React.Component<LinkDocPreviewProps> {
followLink = () => {
LinkDocPreview.Clear();
if (this._linkDoc && this._linkSrc) {
- LinkFollower.FollowLink(this._linkDoc, this._linkSrc, this.props.docProps, false);
+ LinkFollower.FollowLink(this._linkDoc, this._linkSrc, false);
} else if (this.props.hrefs?.length) {
const webDoc =
Array.from(SearchBox.staticSearchCollection(Doc.MyFilesystem, this.props.hrefs[0]).keys()).lastElement() ??
diff --git a/src/client/views/nodes/ScriptingBox.tsx b/src/client/views/nodes/ScriptingBox.tsx
index fa2021642..a6e2c3e90 100644
--- a/src/client/views/nodes/ScriptingBox.tsx
+++ b/src/client/views/nodes/ScriptingBox.tsx
@@ -180,13 +180,15 @@ export class ScriptingBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatable
const params: ScriptParam = {};
this.compileParams.forEach(p => (params[p.split(':')[0].trim()] = p.split(':')[1].trim()));
- const result = CompileScript(this.rawText, {
- editable: true,
- transformer: DocumentIconContainer.getTransformer(),
- params,
- typecheck: false,
- });
- Doc.SetInPlace(this.rootDoc, this.fieldKey, result.compiled ? new ScriptField(result, undefined, this.rawText) : new ScriptField(undefined, undefined, this.rawText), true);
+ const result = !this.rawText.trim()
+ ? ({ compiled: false, errors: undefined } as any)
+ : CompileScript(this.rawText, {
+ editable: true,
+ transformer: DocumentIconContainer.getTransformer(),
+ params,
+ typecheck: false,
+ });
+ Doc.SetInPlace(this.rootDoc, this.fieldKey, result.compiled ? new ScriptField(result, undefined, this.rawText) : undefined, true);
this.onError(result.compiled ? undefined : result.errors);
return result.compiled;
};
diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx
index b1acef44a..f7425b26a 100644
--- a/src/client/views/nodes/WebBox.tsx
+++ b/src/client/views/nodes/WebBox.tsx
@@ -145,6 +145,9 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
const nativeWidth = NumCast(this.layoutDoc.nativeWidth);
const nativeHeight = (nativeWidth * this.props.PanelHeight()) / this.props.PanelWidth();
if (
+ !this.props.isSelected(true) &&
+ !Doc.IsBrushedDegree(this.rootDoc) &&
+ !this.isAnyChildContentActive() &&
!this.rootDoc.thumbLockout &&
!this.props.dontRegisterView &&
this._iframe &&
@@ -181,6 +184,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
});
}
};
+ _thumbTimer: any;
async componentDidMount() {
this.props.setContentView?.(this); // this tells the DocumentView that this WebBox is the "content" of the document. this allows the DocumentView to call WebBox relevant methods to configure the UI (eg, show back/forward buttons)
@@ -197,6 +201,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
() => this.props.isSelected(true) || this.isAnyChildContentActive() || Doc.isBrushedHighlightedDegree(this.props.Document),
async selected => {
if (selected) {
+ this._thumbTimer && clearTimeout(this._thumbTimer);
this._webPageHasBeenRendered = true;
} else if (
(!this.props.isContentActive(true) || SnappingManager.GetIsDragging()) && // update thumnail when unselected AND (no child annotation is active OR we've started dragging the document in which case no additional deselect will occur so this is the only chance to update the thumbnail)
@@ -204,7 +209,8 @@ export class WebBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProps
LightboxView.LightboxDoc !== this.rootDoc
) {
// don't create a thumbnail if entering Lightbox from maximize either, since thumb will be empty.
- this.updateThumb();
+ this._thumbTimer && clearTimeout(this._thumbTimer);
+ this._thumbTimer = setTimeout(this.updateThumb, 2000);
}
},
{ fireImmediately: this.props.isSelected(true) || this.isAnyChildContentActive() || (Doc.isBrushedHighlightedDegreeUnmemoized(this.props.Document) ? true : false) }
diff --git a/src/client/views/nodes/button/ButtonScripts.ts b/src/client/views/nodes/button/ButtonScripts.ts
deleted file mode 100644
index b4a382faf..000000000
--- a/src/client/views/nodes/button/ButtonScripts.ts
+++ /dev/null
@@ -1,16 +0,0 @@
-import { ScriptingGlobals } from "../../../util/ScriptingGlobals";
-import { SelectionManager } from "../../../util/SelectionManager";
-import { Colors } from "../../global/globalEnums";
-
-// toggle: Set overlay status of selected document
-ScriptingGlobals.add(function changeView(view: string) {
- const selected = SelectionManager.Views().length ? SelectionManager.Views()[0] : undefined;
- selected ? selected.Document._viewType = view : console.log("[FontIconBox.tsx] changeView failed");
-});
-
-// toggle: Set overlay status of selected document
-ScriptingGlobals.add(function toggleOverlay(readOnly?: boolean) {
- const selected = SelectionManager.Views().length ? SelectionManager.Views()[0] : undefined;
- if (readOnly) return selected?.Document.z ? Colors.MEDIUM_BLUE : "transparent";
- selected ? selected.props.CollectionFreeFormDocumentView?.().float() : console.log("failed");
-}); \ No newline at end of file
diff --git a/src/client/views/nodes/button/FontIconBox.scss b/src/client/views/nodes/button/FontIconBox.scss
index a1ca777b3..7fe1436c7 100644
--- a/src/client/views/nodes/button/FontIconBox.scss
+++ b/src/client/views/nodes/button/FontIconBox.scss
@@ -43,10 +43,6 @@
cursor: pointer;
flex-direction: column;
- &:hover {
- background-color: rgba(0, 0, 0, 0.3) !important;
- }
-
svg {
width: 50% !important;
height: 50%;
@@ -68,10 +64,6 @@
justify-content: center;
align-items: center;
justify-items: center;
-
- &:hover {
- filter: brightness(0.85) !important;
- }
}
&.tglBtn,
@@ -220,10 +212,6 @@
box-shadow: 0px 3px 4px rgba(0, 0, 0, 0.3);
border-radius: 3px;
}
-
- &:hover {
- background-color: rgba(0, 0, 0, 0.3) !important;
- }
}
&.colorBtnLabel {
@@ -248,10 +236,6 @@
align-content: center;
align-items: center;
- &:hover {
- background-color: rgba(0, 0, 0, 0.3) !important;
- }
-
.menuButton-dropdownList {
position: absolute;
width: 150px;
@@ -283,10 +267,6 @@
cursor: pointer;
background: transparent;
- &:hover {
- background-color: rgba(0, 0, 0, 0.3) !important;
- }
-
&.slider {
color: $white;
cursor: pointer;
diff --git a/src/client/views/nodes/button/FontIconBox.tsx b/src/client/views/nodes/button/FontIconBox.tsx
index 0468d1c47..cb962cad3 100644
--- a/src/client/views/nodes/button/FontIconBox.tsx
+++ b/src/client/views/nodes/button/FontIconBox.tsx
@@ -11,7 +11,7 @@ import { ScriptField } from '../../../../fields/ScriptField';
import { BoolCast, Cast, NumCast, ScriptCast, StrCast } from '../../../../fields/Types';
import { WebField } from '../../../../fields/URLField';
import { GestureUtils } from '../../../../pen-gestures/GestureUtils';
-import { aggregateBounds, StopEvent, Utils } from '../../../../Utils';
+import { aggregateBounds, Utils } from '../../../../Utils';
import { CollectionViewType, DocumentType } from '../../../documents/DocumentTypes';
import { LinkManager } from '../../../util/LinkManager';
import { ScriptingGlobals } from '../../../util/ScriptingGlobals';
@@ -100,7 +100,7 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
return StrCast(this.rootDoc.label, StrCast(this.rootDoc.title));
}
Icon = (color: string) => {
- const icon = StrCast(this.dataDoc.icon, 'user') as any;
+ const icon = StrCast(this.dataDoc[this.fieldKey ?? 'icon'] ?? this.dataDoc.icon, 'user') as any;
const trailsIcon = () => <img src={`/assets/${'presTrails.png'}`} style={{ width: 30, height: 30, filter: `invert(${color === Colors.DARK_GRAY ? '0%' : '100%'})` }} />;
return !icon ? null : icon === 'pres-trail' ? trailsIcon() : <FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={icon} color={color} />;
};
@@ -134,10 +134,10 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
@computed get numberButton() {
const numBtnType: string = StrCast(this.rootDoc.numBtnType);
const numScript = ScriptCast(this.rootDoc.script);
- const setValue = (value: number) => UndoManager.RunInBatch(() => numScript?.script.run({ value, _readOnly_: false }), 'set num value');
+ const setValue = (value: number) => UndoManager.RunInBatch(() => numScript?.script.run({ self: this.rootDoc, value, _readOnly_: false }), 'set num value');
// Script for checking the outcome of the toggle
- const checkResult = Number(numScript?.script.run({ value: 0, _readOnly_: true }).result ?? 0).toPrecision(NumCast(this.dataDoc.numPrecision, 3));
+ const checkResult = Number(numScript?.script.run({ self: this.rootDoc, value: 0, _readOnly_: true }).result ?? 0).toPrecision(NumCast(this.dataDoc.numPrecision, 3));
const label = !FontIconBox.GetShowLabels() ? null : <div className="fontIconBox-label">{this.label}</div>;
@@ -150,7 +150,7 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
min={NumCast(this.rootDoc.numBtnMin, 0)}
max={NumCast(this.rootDoc.numBtnMax, 100)}
value={checkResult}
- className={'menu-slider'}
+ className="menu-slider"
onPointerDown={() => (this._batch = UndoManager.StartBatch('presDuration'))}
onPointerUp={() => this._batch?.end()}
onChange={e => {
@@ -284,27 +284,23 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
text = 'User Default';
}
noviceList = [CollectionViewType.Freeform, CollectionViewType.Schema, CollectionViewType.Stacking, CollectionViewType.NoteTaking];
- } else if (script?.script.originalScript.startsWith('setFont')) {
- const editorView = RichTextMenu.Instance?.TextView?.EditorView;
- text = StrCast((editorView ? RichTextMenu.Instance : Doc.UserDoc()).fontFamily);
- noviceList = ['Roboto', 'Times New Roman', 'Arial', 'Georgia', 'Comic Sans MS', 'Tahoma', 'Impact', 'Crimson Text'];
- }
+ } else text = StrCast((RichTextMenu.Instance?.TextView?.EditorView ? RichTextMenu.Instance : Doc.UserDoc()).fontFamily);
} catch (e) {
console.log(e);
}
// Get items to place into the list
const list = this.buttonList
- .filter(value => !Doc.noviceMode || noviceList.includes(value))
+ .filter(value => !Doc.noviceMode || !noviceList.length || noviceList.includes(value))
.map(value => (
<div
className="list-item"
key={`${value}`}
style={{
- fontFamily: script.script.originalScript.startsWith('setFont') ? value : undefined,
+ fontFamily: script.script.originalScript.startsWith('{ return setFont') ? value : undefined,
backgroundColor: value === text ? Colors.LIGHT_BLUE : undefined,
}}
- onClick={undoBatch(() => script.script.run({ value }))}>
+ onClick={undoBatch(() => script.script.run({ self: this.rootDoc, value }))}>
{value[0].toUpperCase() + value.slice(1)}
</div>
));
@@ -357,7 +353,7 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
ev.preventDefault();
ev.stopPropagation();
const s = this.colorScript;
- s && undoBatch(() => s.script.run({ value: Utils.colorString(value), _readOnly_: false }).result)();
+ s && undoBatch(() => s.script.run({ self: this.rootDoc, value: Utils.colorString(value), _readOnly_: false }).result)();
};
const presets = ['#D0021B', '#F5A623', '#F8E71C', '#8B572A', '#7ED321', '#417505', '#9013FE', '#4A90E2', '#50E3C2', '#B8E986', '#000000', '#4A4A4A', '#9B9B9B', '#FFFFFF', '#f1efeb', 'transparent'];
return <SketchPicker onChange={change as any /* SketchPicker passes the mouse event to the callback, but the type system doesn't know that */} color={curColor} presetColors={presets} />;
@@ -368,7 +364,7 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
@computed get colorButton() {
const color = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Color);
const backgroundColor = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor);
- const curColor = this.colorScript?.script.run({ value: undefined, _readOnly_: true }).result ?? 'transparent';
+ const curColor = this.colorScript?.script.run({ self: this.rootDoc, value: undefined, _readOnly_: true }).result ?? 'transparent';
const label =
!this.label || !FontIconBox.GetShowLabels() ? null : (
@@ -377,13 +373,6 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
</div>
);
- // dropdown caret seems superfluous since clicking the color button does the same thing
- // const dropdownCaret = <div
- // className="menuButton-dropDown"
- // style={{ borderBottomRightRadius: this.dropdown ? 0 : undefined }}>
- // <FontAwesomeIcon icon={'caret-down'} color={color} size="sm" />
- // </div>;
- //setTimeout(() => this.colorPicker(curColor)); // cause an update to the color picker rendered in MainView
return (
<div
className={`menuButton ${this.type + (FontIconBox.GetShowLabels() ? 'Label' : '')} ${this.colorPickerClosed}`}
@@ -598,121 +587,70 @@ ScriptingGlobals.add(function toggleOverlay(checkResult?: boolean) {
selected ? selected.props.CollectionFreeFormDocumentView?.().float() : console.log('[FontIconBox.tsx] toggleOverlay failed');
});
-/** TEXT
- * setFont
- * setFontSize
- * toggleBold
- * toggleUnderline
- * toggleItalic
- * setAlignment
- * toggleBold
- * toggleItalic
- * toggleUnderline
- **/
-
-// toggle: Set overlay status of selected document
-ScriptingGlobals.add(function setFont(font: string, checkResult?: boolean) {
- if (checkResult) return RichTextMenu.Instance?.fontFamily;
- font && RichTextMenu.Instance.setFontFamily(font);
-});
-
-ScriptingGlobals.add(function getActiveTextInfo(info: 'family' | 'size' | 'color' | 'highlight') {
- const editorView = RichTextMenu.Instance.TextView?.EditorView;
- const style = editorView?.state && RichTextMenu.Instance.getActiveFontStylesOnSelection();
- // prettier-ignore
- switch (info) {
- case 'family': return style?.activeFamilies[0];
- case 'size': return style?.activeSizes[0];
- case 'color': return style?.activeColors[0];
- case 'highlight': return style?.activeHighlights[0];
- }
-});
-
-ScriptingGlobals.add(function setAlignment(align: 'left' | 'right' | 'center', checkResult?: boolean) {
- const editorView = RichTextMenu.Instance?.TextView?.EditorView;
- if (checkResult) {
- return (editorView ? RichTextMenu.Instance.textAlign : Doc.UserDoc().textAlign) === align ? Colors.MEDIUM_BLUE : 'transparent';
- }
- if (editorView?.state) RichTextMenu.Instance.align(editorView, editorView.dispatch, align);
- else Doc.UserDoc().textAlign = align;
-});
-
-ScriptingGlobals.add(function setBulletList(mapStyle: 'bullet' | 'decimal', checkResult?: boolean) {
+ScriptingGlobals.add(function setFontAttr(attr: 'font' | 'fontColor' | 'highlight' | 'fontSize', value: any, checkResult?: boolean) {
const editorView = RichTextMenu.Instance?.TextView?.EditorView;
- if (checkResult) {
- const active = editorView?.state && RichTextMenu.Instance.getActiveListStyle();
- if (active === mapStyle) return Colors.MEDIUM_BLUE;
- return 'transparent';
- }
- editorView?.state && RichTextMenu.Instance.changeListType(mapStyle);
-});
-
-// toggle: Set overlay status of selected document
-ScriptingGlobals.add(function setFontColor(color?: string, checkResult?: boolean) {
- if (checkResult) return RichTextMenu.Instance.fontColor;
- color && RichTextMenu.Instance.setColor(color);
-});
-
-// toggle: Set overlay status of selected document
-ScriptingGlobals.add(function setFontHighlight(color?: string, checkResult?: boolean) {
const selected = SelectionManager.Docs().lastElement();
- const editorView = RichTextMenu.Instance.TextView?.EditorView;
+ // prettier-ignore
+ const map: Map<'font'|'fontColor'|'highlight'|'fontSize', { checkResult: () => any; setDoc: () => void; setMode?: () => void }> = new Map([
+ ['font', {
+ checkResult: () => RichTextMenu.Instance?.fontFamily,
+ setDoc: () => value && RichTextMenu.Instance.setFontFamily(value),
+ setMode: () => Doc.UserDoc().textAlign = value,
+ }],
+ ['highlight', {
+ checkResult: () =>(selected ?? Doc.UserDoc())._fontHighlight,
+ setDoc: () => value && RichTextMenu.Instance.setHighlight(value),
+ }],
+ ['fontColor', {
+ checkResult: () => RichTextMenu.Instance?.fontColor,
+ setDoc: () => value && RichTextMenu.Instance.setColor(value),
+ }],
+ ['fontSize', {
+ checkResult: () => RichTextMenu.Instance?.fontSize.replace('px', ''),
+ setDoc: () => {
+ if (typeof value === 'number') value = value.toString();
+ if (value && Number(value).toString() === value) value += 'px';
+ RichTextMenu.Instance.setFontSize(value);
+ },
+ }],
+ ]);
if (checkResult) {
- return (selected ?? Doc.UserDoc())._fontHighlight;
+ return map.get(attr)?.checkResult();
}
- color && RichTextMenu.Instance.setHighlight(color);
+ if (editorView?.state) map.get(attr)?.setDoc();
+ else map.get(attr)?.setMode?.();
});
-// toggle: Set overlay status of selected document
-ScriptingGlobals.add(function setFontSize(size: string | number, checkResult?: boolean) {
- if (checkResult) {
- return RichTextMenu.Instance?.fontSize.replace('px', '');
- }
- if (typeof size === 'number') size = size.toString();
- if (size && Number(size).toString() === size) size += 'px';
- RichTextMenu.Instance.setFontSize(size);
-});
-ScriptingGlobals.add(function toggleNoAutoLinkAnchor(checkResult?: boolean) {
- const editorView = RichTextMenu.Instance?.TextView?.EditorView;
- if (checkResult) {
- return (editorView ? RichTextMenu.Instance.noAutoLink : false) ? Colors.MEDIUM_BLUE : 'transparent';
- }
- if (editorView) RichTextMenu.Instance?.toggleNoAutoLinkAnchor();
-});
-ScriptingGlobals.add(function toggleDictation(checkResult?: boolean) {
+type attrname = 'noAutoLink' | 'dictation' | 'bold' | 'italics' | 'underline' | 'left' | 'center' | 'right' | 'bullet' | 'decimal';
+type attrfuncs = [attrname, { checkResult: () => boolean; toggle: () => any }];
+ScriptingGlobals.add(function toggleCharStyle(charStyle: attrname, checkResult?: boolean) {
const textView = RichTextMenu.Instance?.TextView;
- if (checkResult) {
- return textView?._recording ? Colors.MEDIUM_BLUE : 'transparent';
- }
- if (textView) runInAction(() => (textView._recording = !textView._recording));
-});
-
-ScriptingGlobals.add(function toggleBold(checkResult?: boolean) {
- const editorView = RichTextMenu.Instance?.TextView?.EditorView;
- if (checkResult) {
- return (editorView ? RichTextMenu.Instance.bold : Doc.UserDoc().fontWeight === 'bold') ? Colors.MEDIUM_BLUE : 'transparent';
- }
- if (editorView) RichTextMenu.Instance?.toggleBold();
- else Doc.UserDoc().fontWeight = Doc.UserDoc().fontWeight === 'bold' ? undefined : 'bold';
-});
-
-ScriptingGlobals.add(function toggleUnderline(checkResult?: boolean) {
- const editorView = RichTextMenu.Instance?.TextView?.EditorView;
- if (checkResult) {
- return (editorView ? RichTextMenu.Instance.underline : Doc.UserDoc().textDecoration === 'underline') ? Colors.MEDIUM_BLUE : 'transparent';
- }
- if (editorView) RichTextMenu.Instance?.toggleUnderline();
- else Doc.UserDoc().textDecoration = Doc.UserDoc().textDecoration === 'underline' ? undefined : 'underline';
-});
-
-ScriptingGlobals.add(function toggleItalic(checkResult?: boolean) {
- const editorView = RichTextMenu.Instance?.TextView?.EditorView;
- if (checkResult) {
- return (editorView ? RichTextMenu.Instance.italics : Doc.UserDoc().fontStyle === 'italics') ? Colors.MEDIUM_BLUE : 'transparent';
- }
- if (editorView) RichTextMenu.Instance?.toggleItalics();
- else Doc.UserDoc().fontStyle = Doc.UserDoc().fontStyle === 'italics' ? undefined : 'italics';
+ const editorView = textView?.EditorView;
+ // prettier-ignore
+ const alignments:attrfuncs[] = (['left','right','center'] as ("left"|"center"|"right")[]).map((where) =>
+ [ where, { checkResult: () =>(editorView ? (RichTextMenu.Instance.textAlign ===where): (Doc.UserDoc().textAlign ===where) ? true:false),
+ toggle: () => (editorView?.state ? RichTextMenu.Instance.align(editorView, editorView.dispatch, where):(Doc.UserDoc().textAlign = where))}]);
+ // prettier-ignore
+ const listings:attrfuncs[] = (['bullet','decimal'] as attrname[]).map(list =>
+ [ list, { checkResult: () => (editorView ? RichTextMenu.Instance.getActiveListStyle() === list:false),
+ toggle: () => editorView?.state && RichTextMenu.Instance.changeListType(list) }]);
+ // prettier-ignore
+ const attrs:attrfuncs[] = [
+ ['dictation', { checkResult: () => textView?._recording ? true:false,
+ toggle: () => textView && runInAction(() => (textView._recording = !textView._recording)) }],
+ ['noAutoLink',{ checkResult: () => (editorView ? RichTextMenu.Instance.noAutoLink : false),
+ toggle: () => editorView && RichTextMenu.Instance?.toggleNoAutoLinkAnchor()}],
+ ['bold', { checkResult: () => (editorView ? RichTextMenu.Instance.bold : (Doc.UserDoc().fontWeight === 'bold') ? true:false),
+ toggle: editorView ? RichTextMenu.Instance.toggleBold : () => (Doc.UserDoc().fontWeight = Doc.UserDoc().fontWeight === 'bold' ? undefined : 'bold')}],
+ ['italics', { checkResult: () => (editorView ? RichTextMenu.Instance.italics : (Doc.UserDoc().fontStyle === 'italics') ? true:false),
+ toggle: editorView ? RichTextMenu.Instance.toggleItalics : () => (Doc.UserDoc().fontStyle = Doc.UserDoc().fontStyle === 'italics' ? undefined : 'italics')}],
+ ['underline', { checkResult: () => (editorView ? RichTextMenu.Instance.underline : (Doc.UserDoc().textDecoration === 'underline') ? true:false),
+ toggle: editorView ? RichTextMenu.Instance.toggleUnderline : () => (Doc.UserDoc().textDecoration = Doc.UserDoc().textDecoration === 'underline' ? undefined : 'underline') }]]
+
+ const map = new Map(attrs.concat(alignments).concat(listings));
+ if (checkResult) return map.get(charStyle)?.checkResult() ? Colors.MEDIUM_BLUE : 'transparent';
+ map.get(charStyle)?.toggle();
});
export function checkInksToGroup() {
@@ -832,62 +770,39 @@ function setActiveTool(tool: InkTool | GestureUtils.Gestures, keepPrim: boolean,
ScriptingGlobals.add(setActiveTool, 'sets the active ink tool mode');
// toggle: Set overlay status of selected document
-ScriptingGlobals.add(function setIsInkMask(checkResult?: boolean) {
- const selected = SelectionManager.Docs().lastElement();
- if (checkResult) {
- if (selected?.type === DocumentType.INK) {
- return BoolCast(selected.isInkMask) ? Colors.MEDIUM_BLUE : 'transparent';
- }
- return ActiveIsInkMask() ? Colors.MEDIUM_BLUE : 'transparent';
- }
- SetActiveIsInkMask(!ActiveIsInkMask());
- SelectionManager.Docs()
- .filter(doc => doc.type === DocumentType.INK)
- .map(doc => (doc.isInkMask = !doc.isInkMask));
-});
-
-// toggle: Set overlay status of selected document
-ScriptingGlobals.add(function setFillColor(color?: string, checkResult?: boolean) {
+ScriptingGlobals.add(function setInkProperty(option: 'inkMask' | 'fillColor' | 'strokeWidth' | 'strokeColor', value: any, checkResult?: boolean) {
const selected = SelectionManager.Docs().lastElement();
- if (checkResult) {
- if (selected?.type === DocumentType.INK) {
- return StrCast(selected.fillColor);
- }
- return ActiveFillColor();
- }
- SetActiveFillColor(StrCast(color));
- SelectionManager.Docs()
- .filter(doc => doc.type === DocumentType.INK)
- .map(doc => (doc.fillColor = color));
-});
-
-ScriptingGlobals.add(function setStrokeWidth(width: number, checkResult?: boolean) {
- if (checkResult) {
- const selected = SelectionManager.Docs().lastElement();
- if (selected?.type === DocumentType.INK) {
- return NumCast(selected.strokeWidth);
- }
- return ActiveInkWidth();
- }
- SetActiveInkWidth(width.toString());
- SelectionManager.Docs()
- .filter(doc => doc.type === DocumentType.INK)
- .map(doc => (doc.strokeWidth = Number(width)));
-});
+ // prettier-ignore
+ const map: Map<'inkMask' | 'fillColor' | 'strokeWidth' | 'strokeColor', { checkResult: () => any; setInk: (doc: Doc) => void; setMode: () => void }> = new Map([
+ ['inkMask', {
+ checkResult: () => ((selected?.type === DocumentType.INK ? BoolCast(selected.isInkMask) : ActiveIsInkMask()) ? Colors.MEDIUM_BLUE : 'transparent'),
+ setInk: (doc: Doc) => (doc.isInkMask = !doc.isInkMask),
+ setMode: () => selected?.type !== DocumentType.INK && SetActiveIsInkMask(!ActiveIsInkMask()),
+ }],
+ ['fillColor', {
+ checkResult: () => (selected?.type === DocumentType.INK ? StrCast(selected.fillColor) : ActiveFillColor() ? Colors.MEDIUM_BLUE : 'transparent'),
+ setInk: (doc: Doc) => (doc.fillColor = StrCast(value)),
+ setMode: () => SetActiveFillColor(StrCast(value)),
+ }],
+ [ 'strokeWidth', {
+ checkResult: () => (selected?.type === DocumentType.INK ? NumCast(selected.strokeWidth) : ActiveInkWidth()),
+ setInk: (doc: Doc) => (doc.strokeWidth = NumCast(value)),
+ setMode: () => SetActiveInkWidth(value.toString()),
+ }],
+ ['strokeColor', {
+ checkResult: () => (selected?.type === DocumentType.INK ? NumCast(selected.color) : ActiveInkColor()),
+ setInk: (doc: Doc) => (doc.color = String(value)),
+ setMode: () => SetActiveInkColor(StrCast(value)),
+ }],
+ ]);
-// toggle: Set overlay status of selected document
-ScriptingGlobals.add(function setStrokeColor(color?: string, checkResult?: boolean) {
if (checkResult) {
- const selected = SelectionManager.Docs().lastElement();
- if (selected?.type === DocumentType.INK) {
- return StrCast(selected.color);
- }
- return ActiveInkColor();
+ return map.get(option)?.checkResult();
}
- SetActiveInkColor(StrCast(color));
+ map.get(option)?.setMode();
SelectionManager.Docs()
.filter(doc => doc.type === DocumentType.INK)
- .map(doc => (doc.color = String(color)));
+ .map(doc => map.get(option)?.setInk(doc));
});
/** WEB
diff --git a/src/client/views/nodes/formattedText/DashDocCommentView.tsx b/src/client/views/nodes/formattedText/DashDocCommentView.tsx
index fcd6e0c55..aa269d8d6 100644
--- a/src/client/views/nodes/formattedText/DashDocCommentView.tsx
+++ b/src/client/views/nodes/formattedText/DashDocCommentView.tsx
@@ -32,7 +32,7 @@ export class DashDocCommentView {
};
this.root = ReactDOM.createRoot(this.dom);
- this.root.render(<DashDocCommentViewInternal view={view} getPos={getPos} docid={node.attrs.docid} />);
+ this.root.render(<DashDocCommentViewInternal view={view} getPos={getPos} docId={node.attrs.docId} />);
(this as any).dom = this.dom;
}
@@ -48,7 +48,7 @@ export class DashDocCommentView {
}
interface IDashDocCommentViewInternal {
- docid: string;
+ docId: string;
view: any;
getPos: any;
}
@@ -63,13 +63,13 @@ export class DashDocCommentViewInternal extends React.Component<IDashDocCommentV
}
onPointerLeaveCollapsed(e: any) {
- DocServer.GetRefField(this.props.docid).then(async dashDoc => dashDoc instanceof Doc && Doc.linkFollowUnhighlight());
+ DocServer.GetRefField(this.props.docId).then(async dashDoc => dashDoc instanceof Doc && Doc.linkFollowUnhighlight());
e.preventDefault();
e.stopPropagation();
}
onPointerEnterCollapsed(e: any) {
- DocServer.GetRefField(this.props.docid).then(async dashDoc => dashDoc instanceof Doc && Doc.linkFollowHighlight(dashDoc, false));
+ DocServer.GetRefField(this.props.docId).then(async dashDoc => dashDoc instanceof Doc && Doc.linkFollowHighlight(dashDoc, false));
e.preventDefault();
e.stopPropagation();
}
@@ -82,7 +82,7 @@ export class DashDocCommentViewInternal extends React.Component<IDashDocCommentV
const tr = this.props.view.state.tr.setNodeMarkup(target.pos, undefined, { ...target.node.attrs, hidden: target.node.attrs.hidden ? false : true });
this.props.view.dispatch(tr.setSelection(TextSelection.create(tr.doc, this.props.getPos() + (expand ? 2 : 1)))); // update the attrs
setTimeout(() => {
- expand && DocServer.GetRefField(this.props.docid).then(async dashDoc => dashDoc instanceof Doc && Doc.linkFollowHighlight(dashDoc));
+ expand && DocServer.GetRefField(this.props.docId).then(async dashDoc => dashDoc instanceof Doc && Doc.linkFollowHighlight(dashDoc));
try {
this.props.view.dispatch(this.props.view.state.tr.setSelection(TextSelection.create(this.props.view.state.tr.doc, this.props.getPos() + (expand ? 2 : 1))));
} catch (e) {}
@@ -100,12 +100,12 @@ export class DashDocCommentViewInternal extends React.Component<IDashDocCommentV
const state = this.props.view.state;
for (let i = this.props.getPos() + 1; i < state.doc.content.size; i++) {
const m = state.doc.nodeAt(i);
- if (m && m.type === state.schema.nodes.dashDoc && m.attrs.docid === this.props.docid) {
+ if (m && m.type === state.schema.nodes.dashDoc && m.attrs.docId === this.props.docId) {
return { node: m, pos: i, hidden: m.attrs.hidden } as { node: any; pos: number; hidden: boolean };
}
}
- const dashDoc = state.schema.nodes.dashDoc.create({ width: 75, height: 35, title: 'dashDoc', docid: this.props.docid, float: 'right' });
+ const dashDoc = state.schema.nodes.dashDoc.create({ width: 75, height: 35, title: 'dashDoc', docId: this.props.docId, float: 'right' });
this.props.view.dispatch(state.tr.insert(this.props.getPos() + 1, dashDoc));
setTimeout(() => {
try {
@@ -119,7 +119,7 @@ export class DashDocCommentViewInternal extends React.Component<IDashDocCommentV
return (
<span
className="formattedTextBox-inlineComment"
- id={'DashDocCommentView-' + this.props.docid}
+ id={'DashDocCommentView-' + this.props.docId}
onPointerLeave={this.onPointerLeaveCollapsed}
onPointerEnter={this.onPointerEnterCollapsed}
onPointerUp={this.onPointerUpCollapsed}
diff --git a/src/client/views/nodes/formattedText/DashDocView.tsx b/src/client/views/nodes/formattedText/DashDocView.tsx
index 19ee1fc7b..61345f891 100644
--- a/src/client/views/nodes/formattedText/DashDocView.tsx
+++ b/src/client/views/nodes/formattedText/DashDocView.tsx
@@ -42,7 +42,7 @@ export class DashDocView {
this.root = ReactDOM.createRoot(this.dom);
this.root.render(
- <DashDocViewInternal docid={node.attrs.docid} alias={node.attrs.alias} width={node.attrs.width} height={node.attrs.height} hidden={node.attrs.hidden} fieldKey={node.attrs.fieldKey} tbox={tbox} view={view} node={node} getPos={getPos} />
+ <DashDocViewInternal docId={node.attrs.docId} alias={node.attrs.alias} width={node.attrs.width} height={node.attrs.height} hidden={node.attrs.hidden} fieldKey={node.attrs.fieldKey} tbox={tbox} view={view} node={node} getPos={getPos} />
);
}
destroy() {
@@ -53,7 +53,7 @@ export class DashDocView {
}
interface IDashDocViewInternal {
- docid: string;
+ docId: string;
alias: string;
tbox: FormattedTextBox;
width: string;
@@ -77,7 +77,7 @@ export class DashDocViewInternal extends React.Component<IDashDocViewInternal> {
updateDoc = action((dashDoc: Doc) => {
this._dashDoc = dashDoc;
- this._finalLayout = this.props.docid ? dashDoc : Doc.expandTemplateLayout(Doc.Layout(dashDoc), dashDoc, this.props.fieldKey);
+ this._finalLayout = this.props.docId ? dashDoc : Doc.expandTemplateLayout(Doc.Layout(dashDoc), dashDoc, this.props.fieldKey);
if (this._finalLayout) {
if (!Doc.AreProtosEqual(this._finalLayout, dashDoc)) {
@@ -107,12 +107,12 @@ export class DashDocViewInternal extends React.Component<IDashDocViewInternal> {
super(props);
this._textBox = this.props.tbox;
- DocServer.GetRefField(this.props.docid + this.props.alias).then(async dashDoc => {
+ DocServer.GetRefField(this.props.docId + this.props.alias).then(async dashDoc => {
if (!(dashDoc instanceof Doc)) {
this.props.alias &&
- DocServer.GetRefField(this.props.docid).then(async dashDocBase => {
+ DocServer.GetRefField(this.props.docId).then(async dashDocBase => {
if (dashDocBase instanceof Doc) {
- const aliasedDoc = Doc.MakeAlias(dashDocBase, this.props.docid + this.props.alias);
+ const aliasedDoc = Doc.MakeAlias(dashDocBase, this.props.docId + this.props.alias);
aliasedDoc.layoutKey = 'layout';
this.props.fieldKey && DocUtils.makeCustomViewClicked(aliasedDoc, Docs.Create.StackingDocument, this.props.fieldKey, undefined);
this.updateDoc(aliasedDoc);
@@ -161,12 +161,12 @@ export class DashDocViewInternal extends React.Component<IDashDocViewInternal> {
};
onPointerLeave = () => {
- const ele = document.getElementById('DashDocCommentView-' + this.props.docid) as HTMLDivElement;
+ const ele = document.getElementById('DashDocCommentView-' + this.props.docId) as HTMLDivElement;
ele && (ele.style.backgroundColor = '');
};
onPointerEnter = () => {
- const ele = document.getElementById('DashDocCommentView-' + this.props.docid) as HTMLDivElement;
+ const ele = document.getElementById('DashDocCommentView-' + this.props.docId) as HTMLDivElement;
ele && (ele.style.backgroundColor = 'orange');
};
diff --git a/src/client/views/nodes/formattedText/DashFieldView.tsx b/src/client/views/nodes/formattedText/DashFieldView.tsx
index a89e8b4ed..21ccf3bc7 100644
--- a/src/client/views/nodes/formattedText/DashFieldView.tsx
+++ b/src/client/views/nodes/formattedText/DashFieldView.tsx
@@ -54,7 +54,7 @@ export class DashFieldView {
unclickable={this.unclickable}
getPos={getPos}
fieldKey={node.attrs.fieldKey}
- docid={node.attrs.docid}
+ docId={node.attrs.docId}
width={node.attrs.width}
height={node.attrs.height}
hideKey={node.attrs.hideKey}
@@ -76,7 +76,7 @@ export class DashFieldView {
interface IDashFieldViewInternal {
fieldKey: string;
- docid: string;
+ docId: string;
hideKey: boolean;
tbox: FormattedTextBox;
width: number;
@@ -100,8 +100,8 @@ export class DashFieldViewInternal extends React.Component<IDashFieldViewInterna
this._fieldKey = this.props.fieldKey;
this._textBoxDoc = this.props.tbox.props.Document;
- if (this.props.docid) {
- DocServer.GetRefField(this.props.docid).then(
+ if (this.props.docId) {
+ DocServer.GetRefField(this.props.docId).then(
action(async dashDoc => {
dashDoc instanceof Doc && (this._dashDoc = dashDoc);
})
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index a76f9623a..ddec86606 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -186,7 +186,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
return '';
}
public static GetDocFromUrl(url: string) {
- return url.startsWith(document.location.origin) ? new URL(url).pathname.split('doc/').lastElement() : ''; // docid
+ return url.startsWith(document.location.origin) ? new URL(url).pathname.split('doc/').lastElement() : ''; // docId
}
constructor(props: any) {
@@ -545,7 +545,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
width: target[WidthSym](),
height: target[HeightSym](),
title: 'dashDoc',
- docid: target[Id],
+ docId: target[Id],
float: 'unset',
});
if (!['alias', 'copy'].includes((dragData.dropAction ?? '') as any)) {
@@ -1260,7 +1260,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
DocServer.GetRefField(pdfAnchorId).then(pdfAnchor => {
if (pdfAnchor instanceof Doc) {
const dashField = view.state.schema.nodes.paragraph.create({}, [
- view.state.schema.nodes.dashField.create({ fieldKey: 'text', docid: pdfAnchor[Id], hideKey: true, editable: false }, undefined, [
+ view.state.schema.nodes.dashField.create({ fieldKey: 'text', docId: pdfAnchor[Id], hideKey: true, editable: false }, undefined, [
view.state.schema.marks.linkAnchor.create({
allAnchors: [{ href: `/doc/${this.rootDoc[Id]}`, title: this.rootDoc.title, anchorId: `${this.rootDoc[Id]}` }],
location: 'add:right',
@@ -1485,7 +1485,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
onPointerUp = (e: React.PointerEvent): void => {
const editor = this._editorView!;
const state = editor?.state;
- if (!state || !editor) return;
+ 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)) {
const pcords = editor.posAtCoords({ left: e.clientX, top: e.clientY });
@@ -1669,8 +1669,10 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
};
onKeyDown = (e: React.KeyboardEvent) => {
- if (e.altKey) {
+ if ((e.altKey || e.ctrlKey) && e.key === 't') {
e.preventDefault();
+ e.stopPropagation();
+ this.props.setTitleFocus?.();
return;
}
const state = this._editorView!.state;
@@ -1721,6 +1723,8 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
this._ignoreScroll = true;
this.layoutDoc._scrollTop = this._scrollRef.current.scrollTop;
this._ignoreScroll = false;
+ e.stopPropagation();
+ e.preventDefault();
}
}
};
@@ -1871,7 +1875,18 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FieldViewProps
return styleFromLayoutString?.height === '0px' ? null : (
<div
className="formattedTextBox-cont"
- onWheel={e => this.props.isContentActive() && e.stopPropagation()}
+ ref={r =>
+ r?.addEventListener(
+ 'wheel', // 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)
+ (e: WheelEvent) => {
+ if (this.isContentActive()) {
+ if (!NumCast(this.layoutDoc._scrollTop) && e.deltaY <= 0) e.preventDefault();
+ e.stopPropagation();
+ }
+ },
+ { passive: false }
+ )
+ }
style={{
...(this.props.dontScale
? {}
diff --git a/src/client/views/nodes/formattedText/RichTextRules.ts b/src/client/views/nodes/formattedText/RichTextRules.ts
index 5675776fb..9e9b61db3 100644
--- a/src/client/views/nodes/formattedText/RichTextRules.ts
+++ b/src/client/views/nodes/formattedText/RichTextRules.ts
@@ -89,8 +89,8 @@ export class RichTextRules {
textDoc[inlineLayoutKey] = FormattedTextBox.LayoutString(inlineFieldKey); // create a layout string for the layout key that will render the annotation text
textDoc[inlineFieldKey] = ''; // set a default value for the annotation
const node = (state.doc.resolve(start) as any).nodeAfter;
- const newNode = schema.nodes.dashComment.create({ docid: textDocInline[Id] });
- const dashDoc = schema.nodes.dashDoc.create({ width: 75, height: 35, title: 'dashDoc', docid: textDocInline[Id], float: 'right' });
+ const newNode = schema.nodes.dashComment.create({ docId: textDocInline[Id] });
+ const dashDoc = schema.nodes.dashDoc.create({ width: 75, height: 35, title: 'dashDoc', docId: textDocInline[Id], float: 'right' });
const sm = state.storedMarks || undefined;
const replaced = node
? state.tr
@@ -248,17 +248,17 @@ export class RichTextRules {
// [[fieldKey:Doc]] => show field of doc
new InputRule(new RegExp(/\[\[([a-zA-Z_\? \-0-9]*)(=[a-zA-Z_@\? /\-0-9]*)?(:[a-zA-Z_@:\.\? \-0-9]+)?\]\]$/), (state, match, start, end) => {
const fieldKey = match[1];
- const docid = match[3]?.replace(':', '');
+ const docId = match[3]?.replace(':', '');
const value = match[2]?.substring(1);
if (!fieldKey) {
- if (docid) {
- DocServer.GetRefField(docid).then(docx => {
+ if (docId) {
+ DocServer.GetRefField(docId).then(docx => {
const rstate = this.TextBox.EditorView?.state;
const selection = rstate?.selection.$from.pos;
if (rstate) {
this.TextBox.EditorView?.dispatch(rstate.tr.setSelection(new TextSelection(rstate.doc.resolve(start), rstate.doc.resolve(end - 3))));
}
- const target = (docx instanceof Doc && docx) || Docs.Create.FreeformDocument([], { title: docid, _width: 500, _height: 500 }, docid);
+ const target = (docx instanceof Doc && docx) || Docs.Create.FreeformDocument([], { title: docId, _width: 500, _height: 500 }, docId);
DocUtils.MakeLink({ doc: this.TextBox.getAnchor(true) }, { doc: target }, 'portal to:portal from', undefined);
const fstate = this.TextBox.EditorView?.state;
@@ -274,7 +274,7 @@ export class RichTextRules {
const num = value.match(/^[0-9.]$/);
this.Document[DataSym][fieldKey] = value === 'true' ? true : value === 'false' ? false : num ? Number(value) : value;
}
- const fieldView = state.schema.nodes.dashField.create({ fieldKey, docid, hideKey: false });
+ const fieldView = state.schema.nodes.dashField.create({ fieldKey, docId, hideKey: false });
return state.tr.setSelection(new TextSelection(state.doc.resolve(start), state.doc.resolve(end))).replaceSelectionWith(fieldView, true);
}),
@@ -311,16 +311,16 @@ export class RichTextRules {
const fieldKey = match[1] || '';
const fieldParam = match[2]?.replace('…', '...') || '';
const rawdocid = match[3]?.substring(1);
- const docid = rawdocid ? (!rawdocid.includes('@') ? normalizeEmail(Doc.CurrentUserEmail) + '@' + rawdocid : rawdocid) : undefined;
- if (!fieldKey && !docid) return state.tr;
- docid &&
- DocServer.GetRefField(docid).then(docx => {
+ const docId = rawdocid ? (!rawdocid.includes('@') ? normalizeEmail(Doc.CurrentUserEmail) + '@' + rawdocid : rawdocid) : undefined;
+ if (!fieldKey && !docId) return state.tr;
+ docId &&
+ DocServer.GetRefField(docId).then(docx => {
if (!(docx instanceof Doc && docx)) {
- Docs.Create.FreeformDocument([], { title: rawdocid, _width: 500, _height: 500 }, docid);
+ Docs.Create.FreeformDocument([], { title: rawdocid, _width: 500, _height: 500 }, docId);
}
});
const node = (state.doc.resolve(start) as any).nodeAfter;
- const dashDoc = schema.nodes.dashDoc.create({ width: 75, height: 75, title: 'dashDoc', docid, fieldKey: fieldKey + fieldParam, float: 'unset', alias: Utils.GenerateGuid() });
+ const dashDoc = schema.nodes.dashDoc.create({ width: 75, height: 75, title: 'dashDoc', docId, fieldKey: fieldKey + fieldParam, float: 'unset', alias: Utils.GenerateGuid() });
const sm = state.storedMarks || undefined;
return node ? state.tr.replaceRangeWith(start, end, dashDoc).setStoredMarks([...node.marks, ...(sm ? sm : [])]) : state.tr;
}),
diff --git a/src/client/views/nodes/formattedText/nodes_rts.ts b/src/client/views/nodes/formattedText/nodes_rts.ts
index aa2475dca..6c9d5d31a 100644
--- a/src/client/views/nodes/formattedText/nodes_rts.ts
+++ b/src/client/views/nodes/formattedText/nodes_rts.ts
@@ -176,7 +176,7 @@ export const nodes: { [index: string]: NodeSpec } = {
dashComment: {
attrs: {
- docid: { default: '' },
+ docId: { default: '' },
},
inline: true,
group: 'inline',
@@ -213,7 +213,7 @@ export const nodes: { [index: string]: NodeSpec } = {
title: { default: null },
float: { default: 'left' },
location: { default: 'add:right' },
- docid: { default: '' },
+ docId: { default: '' },
},
group: 'inline',
draggable: true,
@@ -246,7 +246,7 @@ export const nodes: { [index: string]: NodeSpec } = {
float: { default: 'right' },
hidden: { default: false }, // whether dashComment node has toggle the dashDoc's display off
fieldKey: { default: '' },
- docid: { default: '' },
+ docId: { default: '' },
alias: { default: '' },
},
group: 'inline',
@@ -261,7 +261,7 @@ export const nodes: { [index: string]: NodeSpec } = {
inline: true,
attrs: {
fieldKey: { default: '' },
- docid: { default: '' },
+ docId: { default: '' },
hideKey: { default: false },
editable: { default: true },
},
diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx
index be40b3592..e79e7472a 100644
--- a/src/client/views/nodes/trails/PresBox.tsx
+++ b/src/client/views/nodes/trails/PresBox.tsx
@@ -570,9 +570,9 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
}
} else {
if (bestTarget._panX !== activeItem.presPanX || bestTarget._panY !== activeItem.presPanY || bestTarget._viewScale !== activeItem.presViewScale) {
- bestTarget._panX = activeItem.presPanX;
- bestTarget._panY = activeItem.presPanY;
- bestTarget._viewScale = activeItem.presViewScale;
+ bestTarget._panX = activeItem.presPanX ?? bestTarget._panX;
+ bestTarget._panY = activeItem.presPanY ?? bestTarget._panY;
+ bestTarget._viewScale = activeItem.presViewScale ?? bestTarget._viewScale;
changed = true;
}
}
@@ -717,6 +717,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
zoomTime: activeItem.presMovement === PresMovement.Jump ? 0 : Math.min(Math.max(effect ? 750 : 500, (effect ? 0.2 : 1) * presTime), presTime),
effect: activeItem,
noSelect: true,
+ openLocation: OpenWhere.addLeft,
anchorDoc: activeItem,
easeFunc: StrCast(activeItem.presEaseFunc, 'ease') as any,
zoomTextSelections: BoolCast(activeItem.presZoomText),