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.tsx3
-rw-r--r--src/client/views/nodes/CollectionFreeFormDocumentView.tsx22
-rw-r--r--src/client/views/nodes/ContentFittingDocumentView.tsx66
-rw-r--r--src/client/views/nodes/DocHolderBox.tsx6
-rw-r--r--src/client/views/nodes/DocumentContentsView.tsx2
-rw-r--r--src/client/views/nodes/DocumentView.scss6
-rw-r--r--src/client/views/nodes/DocumentView.tsx80
-rw-r--r--src/client/views/nodes/FieldView.tsx5
-rw-r--r--src/client/views/nodes/FilterBox.tsx5
-rw-r--r--src/client/views/nodes/FontIconBox.tsx2
-rw-r--r--src/client/views/nodes/ImageBox.tsx3
-rw-r--r--src/client/views/nodes/KeyValueBox.tsx2
-rw-r--r--src/client/views/nodes/KeyValuePair.tsx1
-rw-r--r--src/client/views/nodes/LinkAnchorBox.tsx2
-rw-r--r--src/client/views/nodes/LinkBox.tsx2
-rw-r--r--src/client/views/nodes/LinkDocPreview.tsx4
-rw-r--r--src/client/views/nodes/PresBox.tsx2
-rw-r--r--src/client/views/nodes/ScriptingBox.scss6
-rw-r--r--src/client/views/nodes/ScriptingBox.tsx14
-rw-r--r--src/client/views/nodes/VideoBox.tsx2
-rw-r--r--src/client/views/nodes/WebBox.tsx13
-rw-r--r--src/client/views/nodes/formattedText/DashDocView.tsx2
-rw-r--r--src/client/views/nodes/formattedText/FormattedTextBox.scss3
-rw-r--r--src/client/views/nodes/formattedText/FormattedTextBox.tsx21
-rw-r--r--src/client/views/nodes/formattedText/RichTextSchema.tsx2
-rw-r--r--src/client/views/nodes/formattedText/marks_rts.ts2
26 files changed, 147 insertions, 131 deletions
diff --git a/src/client/views/nodes/AudioBox.tsx b/src/client/views/nodes/AudioBox.tsx
index cba65f663..6323a6100 100644
--- a/src/client/views/nodes/AudioBox.tsx
+++ b/src/client/views/nodes/AudioBox.tsx
@@ -623,9 +623,8 @@ export class AudioBox extends ViewBoxAnnotatableComponent<FieldViewProps, AudioD
ContainingCollectionDoc={this.props.Document}
parentActive={returnTrue}
bringToFront={emptyFunction}
- backgroundColor={returnTransparent}
ContentScaling={returnOne}
- forcedBackgroundColor={returnTransparent}
+ styleProvider={(doc: Opt<Doc>, renderDepth: number, property: string) => property === "backgroundColor" ? "transparent" : undefined}
pointerEvents={"none"}
LayoutTemplate={undefined}
LayoutTemplateString={LinkAnchorBox.LayoutString(`anchor${Doc.LinkEndpoint(l, la2)}`)}
diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
index c87239ee9..84f08b217 100644
--- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
+++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
@@ -1,4 +1,4 @@
-import { computed, IReactionDisposer, observable, reaction, trace } from "mobx";
+import { computed, IReactionDisposer, observable, reaction, trace, action } from "mobx";
import { observer } from "mobx-react";
import { Doc, HeightSym, WidthSym } from "../../../fields/Doc";
import { Cast, NumCast, StrCast } from "../../../fields/Types";
@@ -18,10 +18,13 @@ import { DocumentType } from "../../documents/DocumentTypes";
import { Zoom, Fade, Flip, Rotate, Bounce, Roll, LightSpeed } from 'react-reveal';
import { PresBox, PresEffect } from "./PresBox";
import { InkingStroke } from "../InkingStroke";
+import { SnappingManager } from "../../util/SnappingManager";
+import { InkTool } from "../../../fields/InkField";
export interface CollectionFreeFormDocumentViewProps extends DocumentViewProps {
dataProvider?: (doc: Doc, replica: string) => { x: number, y: number, zIndex?: number, opacity?: number, highlight?: boolean, z: number, transition?: string } | undefined;
sizeProvider?: (doc: Doc, replica: string) => { width: number, height: number } | undefined;
+ layerProvider?: (doc: Doc, assign?: boolean) => boolean;
zIndex?: number;
highlight?: boolean;
jitterRotation: number;
@@ -33,6 +36,7 @@ export interface CollectionFreeFormDocumentViewProps extends DocumentViewProps {
@observer
export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeFormDocumentViewProps, Document>(Document) {
@observable _animPos: number[] | undefined = undefined;
+ @observable _contentView: ContentFittingDocumentView | undefined | null;
random(min: number, max: number) { // min should not be equal to max
const mseed = Math.abs(this.X * this.Y);
const seed = (mseed * 9301 + 49297) % 233280;
@@ -204,8 +208,9 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
dragDivName={"collectionFreeFormDocumentView-container"}
ContentScaling={this.contentScaling}
ScreenToLocalTransform={this.getTransform}
- backgroundColor={this.props.backgroundColor}
+ styleProvider={this.props.styleProvider}
opacity={this.opacity}
+ layerProvider={this.props.layerProvider}
NativeHeight={this.NativeHeight}
NativeWidth={this.NativeWidth}
PanelWidth={this.panelWidth}
@@ -244,17 +249,21 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
opacity = () => this.Opacity;
NativeWidth = () => this.nativeWidth;
NativeHeight = () => this.nativeHeight;
+ @computed get pointerEvents() {
+ if (this.props.pointerEvents === "none") return "none";
+ return this.props.styleProvider?.(this.Document, this.props.renderDepth, !this._contentView?.docView?.isSelected() ? "pointerEvents:selected" : "pointerEvents", this.props.layerProvider);
+ }
render() {
TraceMobx();
- const backgroundColor = StrCast(this.layoutDoc._backgroundColor) || StrCast(this.layoutDoc.backgroundColor) || StrCast(this.Document.backgroundColor) || this.props.backgroundColor?.(this.Document, this.props.renderDepth);
+ const backgroundColor = this.props.styleProvider?.(this.Document, this.props.renderDepth, "backgroundColor", this.props.layerProvider);
const borderRounding = StrCast(Doc.Layout(this.layoutDoc).borderRounding) || StrCast(this.layoutDoc.borderRounding) || StrCast(this.Document.borderRounding) || undefined;
return <div className="collectionFreeFormDocumentView-container"
style={{
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.Document.type !== DocumentType.INK ? (`${this.props.backgroundColor?.(this.props.Document, this.props.renderDepth)} ${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
+ this.props.backgroundHalo?.(this.props.Document) && this.props.Document.type !== DocumentType.INK ? (`${this.props.styleProvider?.(this.props.Document, this.props.renderDepth, "backgroundColor", this.props.layerProvider)} ${StrCast(this.layoutDoc.boxShadow, `0vw 0vw ${(Cast(this.layoutDoc.layers, listSpec("string"), []).includes("background") ? 100 : 50) / this.props.ContentScaling()}px`)}`) : // if it's just in a cluster, make the shadown roughly match the cluster border extent
+ Cast(this.layoutDoc.layers, listSpec("string"), []).includes('background') ? undefined : // if it's a background & has a cluster color, make the shadow spread really big
StrCast(this.layoutDoc.boxShadow, ""),
borderRadius: borderRounding,
outline: this.Highlight ? "orange solid 2px" : "",
@@ -266,7 +275,7 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
mixBlendMode: StrCast(this.layoutDoc.mixBlendMode) as any,
display: this.ZInd === -99 ? "none" : undefined,
// @ts-ignore
- pointerEvents: this.props.Document._isBackground || this.Opacity === 0 || this.props.Document.type === DocumentType.INK || this.props.Document.isInkMask ? "none" : this.props.pointerEvents
+ pointerEvents: this.pointerEvents
}} >
{Doc.UserDoc().renderStyle !== "comic" ? (null) :
@@ -280,6 +289,7 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
{!this.props.fitToBox ?
<>{this.freeformNodeDiv}</>
: <ContentFittingDocumentView {...this.props}
+ ref={action((r: ContentFittingDocumentView | null) => this._contentView = r)}
ContainingCollectionDoc={this.props.ContainingCollectionDoc}
DataDoc={this.props.DataDoc}
ScreenToLocalTransform={this.getTransform}
diff --git a/src/client/views/nodes/ContentFittingDocumentView.tsx b/src/client/views/nodes/ContentFittingDocumentView.tsx
index 0c52b9044..a54479f55 100644
--- a/src/client/views/nodes/ContentFittingDocumentView.tsx
+++ b/src/client/views/nodes/ContentFittingDocumentView.tsx
@@ -1,87 +1,85 @@
import React = require("react");
-import { computed } from "mobx";
+import { computed, observable, action } from "mobx";
import { observer } from "mobx-react";
import { Doc, HeightSym, WidthSym } from "../../../fields/Doc";
-import { Cast, NumCast, StrCast } from "../../../fields/Types";
+import { Cast, StrCast } from "../../../fields/Types";
import { TraceMobx } from "../../../fields/util";
-import { emptyFunction, OmitKeys, returnVal } from "../../../Utils";
+import { emptyFunction, OmitKeys, returnVal, returnOne } from "../../../Utils";
import { DocumentView, DocumentViewProps } from "../nodes/DocumentView";
import "./ContentFittingDocumentView.scss";
interface ContentFittingDocumentViewProps {
- dontCenter?: boolean;
+ dontCenter?: string; // "x" ,"y", "xy"
}
@observer
export class ContentFittingDocumentView extends React.Component<DocumentViewProps & ContentFittingDocumentViewProps> {
public get displayName() { return "DocumentView(" + this.props.Document?.title + ")"; } // this makes mobx trace() statements more descriptive
- private get layoutDoc() {
+ public ContentRef = React.createRef<HTMLDivElement>();
+ @observable public docView: DocumentView | undefined | null;
+ @computed get layoutDoc() {
return this.props.LayoutTemplate?.() ||
(this.props.layoutKey && Doc.Layout(this.props.Document, Cast(this.props.Document[this.props.layoutKey], Doc, null))) ||
Doc.Layout(this.props.Document);
}
@computed get freezeDimensions() { return this.props.FreezeDimensions; }
-
- nativeWidth = () => returnVal(this.props.NativeWidth?.(), Doc.NativeWidth(this.layoutDoc, this.props.DataDoc, this.freezeDimensions) || this.props.PanelWidth());
- nativeHeight = () => returnVal(this.props.NativeHeight?.(), Doc.NativeHeight(this.layoutDoc, this.props.DataDoc, this.freezeDimensions) || this.props.PanelHeight());
- @computed get scaling() {
- const wscale = this.props.PanelWidth() / this.nativeWidth();
- const hscale = this.props.PanelHeight() / this.nativeHeight();
- if (wscale * this.nativeHeight() > this.props.PanelHeight()) {
+ @computed get nativeWidth() { return !this.layoutDoc._fitWidth && returnVal(this.props.NativeWidth?.(), Doc.NativeWidth(this.layoutDoc, this.props.DataDoc, this.freezeDimensions)); }
+ @computed get nativeHeight() { return returnVal(this.props.NativeHeight?.(), Doc.NativeHeight(this.layoutDoc, this.props.DataDoc, this.freezeDimensions) || 0); }
+ @computed get nativeScaling() {
+ if (!this.nativeWidth || !this.nativeHeight) return 1;
+ const wscale = this.props.PanelWidth() / this.nativeWidth;
+ const hscale = this.props.PanelHeight() / this.nativeHeight;
+ if (wscale * this.nativeHeight > this.props.PanelHeight()) {
return hscale || 1;
}
return wscale || 1;
}
- private contentScaling = () => this.scaling;
-
- private PanelWidth = () => this.panelWidth;
- private PanelHeight = () => this.panelHeight;
- @computed get panelWidth() { return this.nativeWidth() && !this.props.Document._fitWidth ? this.nativeWidth() * this.contentScaling() : this.props.PanelWidth(); }
+ @computed get panelWidth() { return this.nativeWidth ? this.nativeWidth * this.nativeScaling : this.props.PanelWidth(); }
@computed get panelHeight() {
- if (this.nativeHeight()) {
- if (!this.props.Document._fitWidth) return this.nativeHeight() * this.contentScaling();
- else return this.panelWidth / Doc.NativeAspect(this.layoutDoc, this.props.DataDoc, this.freezeDimensions) || 1;
+ if (this.nativeHeight) {
+ if (this.props.Document._fitWidth) return Math.min(this.props.PanelHeight(), this.panelWidth / Doc.NativeAspect(this.layoutDoc, this.props.DataDoc, this.freezeDimensions) || 1);
+ return Math.min(this.props.PanelHeight(), this.nativeHeight * this.nativeScaling);
}
return this.props.PanelHeight();
}
- @computed get childXf() { return this.props.DataDoc ? 1 : 1 / this.contentScaling(); } // this is intended to detect when a document is being rendered inside itself as part of a template, but not as a leaf node where nativeWidth & height would apply.
- private getTransform = () => this.props.dontCenter ?
- this.props.ScreenToLocalTransform().scale(this.childXf) :
- this.props.ScreenToLocalTransform().translate(-this.centeringOffset, -this.centeringYOffset).scale(this.childXf)
- private get centeringOffset() { return this.nativeWidth() && !this.props.Document._fitWidth ? (this.props.PanelWidth() - this.nativeWidth() * this.contentScaling()) / 2 : 0; }
- private get centeringYOffset() { return Math.abs(this.centeringOffset) < 0.001 ? (this.props.PanelHeight() - this.nativeHeight() * this.contentScaling()) / 2 : 0; }
+ private getTransform = () => this.props.ScreenToLocalTransform().
+ translate(this.props.dontCenter?.includes("x") ? 0 : -this.centeringOffset, this.props.dontCenter?.includes("y") ? 0 : -this.centeringYOffset)
+ private get centeringOffset() { return this.nativeWidth && !this.props.Document._fitWidth ? (this.props.PanelWidth() - this.nativeWidth * this.nativeScaling) / 2 : 0; }
+ private get centeringYOffset() { return this.nativeWidth && Math.abs(this.centeringOffset) < 0.001 && this.nativeHeight ? (this.props.PanelHeight() - this.nativeHeight * this.nativeScaling) / 2 : 0; }
@computed get borderRounding() { return StrCast(this.props.Document?.borderRounding); }
+ PanelWidth = () => this.panelWidth;
+ PanelHeight = () => this.panelHeight;
+
render() {
TraceMobx();
return (<div className="contentFittingDocumentView">
{!this.props.Document || !this.props.PanelWidth ? (null) : (
- <div className="contentFittingDocumentView-previewDoc"
+ <div className="contentFittingDocumentView-previewDoc" ref={this.ContentRef}
style={{
- transform: !this.props.dontCenter ? `translate(${this.centeringOffset}px, ${this.centeringYOffset}px)` : undefined,
+ transform: `translate(${this.props.dontCenter?.includes("x") ? 0 : this.centeringOffset}px, ${this.props.dontCenter?.includes("y") ? 0 : this.centeringYOffset}px)`,
borderRadius: this.borderRounding,
- height: Math.abs(this.centeringYOffset) > 0.001 ? `${100 * this.nativeHeight() / this.nativeWidth() * this.props.PanelWidth() / this.props.PanelHeight()}%` : this.props.PanelHeight(),
- width: Math.abs(this.centeringOffset) > 0.001 ? `${100 * (this.props.PanelWidth() - this.centeringOffset * 2) / this.props.PanelWidth()}%` : this.props.PanelWidth()
+ height: Math.abs(this.centeringYOffset) > 0.001 && this.nativeWidth ? `${100 * this.nativeHeight / this.nativeWidth * this.props.PanelWidth() / this.props.PanelHeight()}%` : this.props.PanelHeight(),
+ width: Math.abs(this.centeringOffset) > 0.001 ? `${100 * (this.props.PanelWidth() - this.centeringOffset * 2) / this.props.PanelWidth()}%` : this.props.PanelWidth(),
}}>
<DocumentView {...OmitKeys(this.props, ["NativeWidth", "NativeHeight"]).omit}
+ ref={action((r: DocumentView | null) => this.docView = r)}
Document={this.props.Document}
DataDoc={this.props.DataDoc}
LayoutTemplate={this.props.LayoutTemplate}
LayoutTemplateString={this.props.LayoutTemplateString}
LibraryPath={this.props.LibraryPath}
- // NativeWidth={this.nativeWidth}
- // NativeHeight={this.nativeHeight}
PanelWidth={this.PanelWidth}
PanelHeight={this.PanelHeight}
- ContentScaling={this.contentScaling}
+ ContentScaling={returnOne}
fitToBox={this.props.fitToBox}
layoutKey={this.props.layoutKey}
dropAction={this.props.dropAction}
onClick={this.props.onClick}
- backgroundColor={this.props.backgroundColor}
+ styleProvider={this.props.styleProvider}
addDocument={this.props.addDocument}
removeDocument={this.props.removeDocument}
moveDocument={this.props.moveDocument}
diff --git a/src/client/views/nodes/DocHolderBox.tsx b/src/client/views/nodes/DocHolderBox.tsx
index dd254ae93..58f4df823 100644
--- a/src/client/views/nodes/DocHolderBox.tsx
+++ b/src/client/views/nodes/DocHolderBox.tsx
@@ -125,7 +125,7 @@ export class DocHolderBox extends ViewBoxAnnotatableComponent<FieldViewProps, Do
ContainingCollectionView={this as any} // bcz: hack! need to pass a prop that can be used to select the container (ie, 'this') when the up selector in document decorations is clicked. currently, the up selector allows only a containing collection to be selected
ContainingCollectionDoc={undefined}
fitToBox={true}
- backgroundColor={this.props.backgroundColor}
+ styleProvider={this.props.styleProvider}
LayoutTemplateString={layoutTemplate}
LayoutTemplate={this.layoutTemplateDoc}
rootSelected={this.props.isSelected}
@@ -154,7 +154,7 @@ export class DocHolderBox extends ViewBoxAnnotatableComponent<FieldViewProps, Do
ContainingCollectionView={this as any} // bcz: hack! need to pass a prop that can be used to select the container (ie, 'this') when the up selector in document decorations is clicked. currently, the up selector allows only a containing collection to be selected
ContainingCollectionDoc={undefined}
fitToBox={true}
- backgroundColor={this.props.backgroundColor}
+ styleProvider={this.props.styleProvider}
ignoreAutoHeight={true}
LayoutTemplateString={layoutTemplate}
LayoutTemplate={this.layoutTemplateDoc}
@@ -184,7 +184,7 @@ export class DocHolderBox extends ViewBoxAnnotatableComponent<FieldViewProps, Do
onContextMenu={this.specificContextMenu}
onPointerDown={this.onPointerDown} onClick={this.onClick}
style={{
- background: this.props.backgroundColor?.(containedDoc, this.props.renderDepth),
+ background: this.props.styleProvider?.(containedDoc, this.props.renderDepth, "backgroundColor", this.props.layerProvider),
border: `#00000021 solid ${this.xPad}px`,
borderTop: `#0000005e solid ${this.yPad}px`,
borderBottom: `#0000005e solid ${this.yPad}px`,
diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx
index e8c3662aa..98a1b026d 100644
--- a/src/client/views/nodes/DocumentContentsView.tsx
+++ b/src/client/views/nodes/DocumentContentsView.tsx
@@ -139,7 +139,7 @@ export class DocumentContentsView extends React.Component<DocumentViewProps & Fo
CreateBindings(onClick: Opt<ScriptField>, onInput: Opt<ScriptField>): JsxBindings {
const list = {
- ...OmitKeys(this.props, ['parentActive', 'NativeWidth', 'NativeHeight'], "", (obj: any) => obj.active = this.props.parentActive).omit,
+ ...OmitKeys(this.props, ['NativeWidth', 'NativeHeight'], "", (obj: any) => obj.active = this.props.parentActive).omit,
RootDoc: Cast(this.layoutDoc?.rootDocument, Doc, null) || this.layoutDoc,
Document: this.layoutDoc,
DataDoc: this.dataDoc,
diff --git a/src/client/views/nodes/DocumentView.scss b/src/client/views/nodes/DocumentView.scss
index c31172e22..ad72250b6 100644
--- a/src/client/views/nodes/DocumentView.scss
+++ b/src/client/views/nodes/DocumentView.scss
@@ -54,6 +54,12 @@
}
}
+ .documentView-contentsView {
+ border-radius: inherit;
+ width: 100%;
+ height: 100%;
+ }
+
.documentView-anchorCont {
position: absolute;
top: 0;
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 77f63b457..62a2b5bc5 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -1,7 +1,7 @@
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { action, computed, observable, runInAction } from "mobx";
import { observer } from "mobx-react";
-import { AclAdmin, AclEdit, AclPrivate, DataSym, Doc, DocListCast, Field, HeightSym, Opt, WidthSym } from "../../../fields/Doc";
+import { AclAdmin, AclEdit, AclPrivate, DataSym, Doc, DocListCast, Field, HeightSym, Opt, WidthSym, StrListCast } from "../../../fields/Doc";
import { Document } from '../../../fields/documentSchemas';
import { Id } from '../../../fields/FieldSymbols';
import { InkTool } from '../../../fields/InkField';
@@ -12,7 +12,7 @@ import { BoolCast, Cast, NumCast, ScriptCast, StrCast } from "../../../fields/Ty
import { GetEffectiveAcl, TraceMobx } from '../../../fields/util';
import { MobileInterface } from '../../../mobile/MobileInterface';
import { GestureUtils } from '../../../pen-gestures/GestureUtils';
-import { emptyFunction, OmitKeys, returnOne, returnTransparent, returnVal, Utils } from "../../../Utils";
+import { emptyFunction, OmitKeys, returnOne, returnTransparent, returnVal, Utils, returnFalse, returnTrue } from "../../../Utils";
import { GooglePhotos } from '../../apis/google_docs/GooglePhotosClientUtils';
import { Docs, DocUtils } from "../../documents/Documents";
import { DocumentType } from '../../documents/DocumentTypes';
@@ -41,6 +41,7 @@ import { LinkDescriptionPopup } from './LinkDescriptionPopup';
import { RadialMenu } from './RadialMenu';
import { TaskCompletionBox } from './TaskCompletedBox';
import React = require("react");
+import { List } from '../../../fields/List';
export type DocAfterFocusFunc = (notFocused: boolean) => boolean;
export type DocFocusFunc = (doc: Doc, willZoom?: boolean, scale?: number, afterFocus?: DocAfterFocusFunc, dontCenter?: boolean, focused?: boolean) => void;
@@ -49,6 +50,7 @@ export interface DocumentViewProps {
ContainingCollectionView: Opt<CollectionView>;
ContainingCollectionDoc: Opt<Doc>;
docFilters: () => string[];
+ contentsActive?: (setActive: () => boolean) => void;
docRangeFilters: () => string[];
searchFilterDocs: () => Doc[];
FreezeDimensions?: boolean;
@@ -56,6 +58,7 @@ export interface DocumentViewProps {
NativeHeight?: () => number;
Document: Doc;
DataDoc?: Doc;
+ layerProvider?: (doc: Doc, assign?: boolean) => boolean;
getView?: (view: DocumentView) => any;
LayoutTemplateString?: string;
LayoutTemplate?: () => Opt<Doc>;
@@ -89,9 +92,9 @@ export interface DocumentViewProps {
bringToFront: (doc: Doc, sendToBack?: boolean) => void;
addDocTab: (doc: Doc, where: string, libraryPath?: Doc[]) => boolean;
pinToPres: (document: Doc) => void;
- backgroundHalo?: () => boolean;
- backgroundColor?: (doc: Opt<Doc>, renderDepth: number) => string | undefined;
- forcedBackgroundColor?: (doc: Doc) => string | undefined;
+ backgroundHalo?: (doc: Doc) => boolean;
+ styleProvider?: (doc: Opt<Doc>, renderDepth: number, property: string, layerProvider?: (doc: Doc, assign?: boolean) => boolean) => any;
+ forceHideLinkButton?: () => boolean;
opacity?: () => number | undefined;
ChromeHeight?: () => number;
dontRegisterView?: boolean;
@@ -118,7 +121,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
private _holdDisposer?: InteractionUtils.MultiTouchEventDisposer;
protected _multiTouchDisposer?: InteractionUtils.MultiTouchEventDisposer;
- private get active() { return SelectionManager.IsSelected(this, true) || this.props.parentActive(true); }
+ private get active() { return this.isSelected(true) || this.props.parentActive(true); }
public get displayName() { return "DocumentView(" + this.props.Document.title + ")"; } // this makes mobx trace() statements more descriptive
public get ContentDiv() { return this._mainCont.current; }
public get LayoutFieldKey() { return this.props.layoutKey || Doc.LayoutFieldKey(this.layoutDoc); }
@@ -312,7 +315,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
(Math.abs(e.clientX - this._downX) < Utils.DRAG_THRESHOLD && Math.abs(e.clientY - this._downY) < Utils.DRAG_THRESHOLD)) {
let stopPropagate = true;
let preventDefault = true;
- !this.props.Document._isBackground && (this.rootDoc._raiseWhenDragged === undefined ? Doc.UserDoc()._raiseWhenDragged : this.rootDoc._raiseWhenDragged) && this.props.bringToFront(this.rootDoc);
+ !Cast(this.props.Document.layers, listSpec("string"), []).includes("background") && (this.rootDoc._raiseWhenDragged === undefined ? Doc.UserDoc()._raiseWhenDragged : this.rootDoc._raiseWhenDragged) && this.props.bringToFront(this.rootDoc);
if (this._doubleTap && ((this.props.renderDepth && this.props.Document.type !== DocumentType.FONTICON) || this.onDoubleClickHandler)) {// && !this.onClickHandler?.script) { // disable double-click to show full screen for things that have an on click behavior since clicking them twice can be misinterpreted as a double click
if (this._timeout) {
clearTimeout(this._timeout);
@@ -742,19 +745,6 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
this.Document.isLinkButton = true;
}
- @undoBatch
- @action
- toggleBackground = () => {
- this.Document._isBackground = (this.Document._isBackground ? undefined : true);
- this.Document._overflow = this.Document._isBackground ? "visible" : undefined;
- if (this.Document._isBackground) {
- this.props.bringToFront(this.props.Document, true);
- const wid = this.Document[WidthSym](); // change the nativewidth and height if the background is to be a collection that aggregates stuff that is added to it.
- const hgt = this.Document[HeightSym]();
- Doc.SetNativeWidth(this.props.Document[DataSym], wid);
- Doc.SetNativeHeight(this.props.Document[DataSym], hgt);
- }
- }
@action
onCopy = () => {
@@ -811,8 +801,8 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
const zorders = cm.findByDescription("ZOrder...");
const zorderItems: ContextMenuProps[] = zorders && "subitems" in zorders ? zorders.subitems : [];
- zorderItems.push({ description: "Bring to Front", event: () => this.props.bringToFront(this.rootDoc, false), icon: "expand-arrows-alt" });
- zorderItems.push({ description: "Send to Back", event: () => this.props.bringToFront(this.rootDoc, true), icon: "expand-arrows-alt" });
+ zorderItems.push({ description: "Bring to Front", event: () => SelectionManager.SelectedDocuments().forEach(dv => dv.props.bringToFront(dv.rootDoc, false)), icon: "expand-arrows-alt" });
+ zorderItems.push({ description: "Send to Back", event: () => SelectionManager.SelectedDocuments().forEach(dv => dv.props.bringToFront(dv.rootDoc, true)), icon: "expand-arrows-alt" });
zorderItems.push({ description: this.rootDoc._raiseWhenDragged !== false ? "Keep ZIndex when dragged" : "Allow ZIndex to change when dragged", event: this.toggleRaiseWhenDragged, icon: "expand-arrows-alt" });
!zorders && cm.addItem({ description: "ZOrder...", subitems: zorderItems, icon: "compass" });
@@ -918,11 +908,15 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
}
childScaling = () => (this.layoutDoc._fitWidth ? this.props.PanelWidth() / this.nativeWidth : this.props.ContentScaling());
@computed.struct get linkOffset() { return this.topMost ? [0, undefined, undefined, 10] : [-15, undefined, undefined, -20]; }
+ @observable contentsActive: () => boolean = returnFalse;
+ @action setContentsActive = (setActive: () => boolean) => this.contentsActive = setActive;
+ parentActive = (outsideReaction: boolean) => this.props.layerProvider?.(this.layoutDoc) === false ? this.props.parentActive(outsideReaction) : false;
@computed get contents() {
TraceMobx();
- return (<div className="documentView-contentsView" style={{ pointerEvents: this.props.contentsPointerEvents as any, borderRadius: "inherit", width: "100%", height: "100%" }}>
+ return (<div className="documentView-contentsView" style={{ pointerEvents: this.props.contentsPointerEvents as any }}>
<DocumentContentsView key={1}
docFilters={this.props.docFilters}
+ contentsActive={this.setContentsActive}
docRangeFilters={this.props.docRangeFilters}
searchFilterDocs={this.props.searchFilterDocs}
ContainingCollectionView={this.props.ContainingCollectionView}
@@ -931,6 +925,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
NativeHeight={this.NativeHeight}
Document={this.props.Document}
DataDoc={this.props.DataDoc}
+ layerProvider={this.props.layerProvider}
LayoutTemplateString={this.props.LayoutTemplateString}
LayoutTemplate={this.props.LayoutTemplate}
makeLink={this.makeLink}
@@ -948,12 +943,12 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
PanelHeight={this.props.PanelHeight}
ignoreAutoHeight={this.props.ignoreAutoHeight}
focus={this.props.focus}
- parentActive={this.props.parentActive}
+ parentActive={this.parentActive}
whenActiveChanged={this.props.whenActiveChanged}
bringToFront={this.props.bringToFront}
addDocTab={this.props.addDocTab}
pinToPres={this.props.pinToPres}
- backgroundColor={this.props.backgroundColor}
+ styleProvider={this.props.styleProvider}
ContentScaling={this.childScaling}
ChromeHeight={this.chromeHeight}
isSelected={this.isSelected}
@@ -963,7 +958,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
layoutKey={this.finalLayoutKey} />
{this.layoutDoc.hideAllLinks ? (null) : this.allAnchors}
{/* {this.allAnchors} */}
- {this.props.forcedBackgroundColor?.(this.Document) === "transparent" || (!this.isSelected() && (this.layoutDoc.isLinkButton || this.layoutDoc.hideLinkButton)) || this.props.dontRegisterView ? (null) :
+ {this.props.forceHideLinkButton?.() || (!this.isSelected() && (this.layoutDoc.isLinkButton || this.layoutDoc.hideLinkButton)) || this.props.dontRegisterView ? (null) :
<DocumentLinksButton View={this} links={this.allLinks} Offset={this.linkOffset} />}
</div>
);
@@ -1008,7 +1003,8 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
PanelHeight={this.anchorPanelHeight}
ContentScaling={returnOne}
dontRegisterView={false}
- forcedBackgroundColor={returnTransparent}
+ forceHideLinkButton={returnTrue}
+ styleProvider={(doc: Opt<Doc>, renderDepth: number, property: string) => property === "backgroundColor" ? "transparent" : undefined}
removeDocument={this.hideLinkAnchor}
pointerEvents={"none"}
LayoutTemplate={undefined}
@@ -1068,10 +1064,9 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
{captionView}
</div>;
}
- @computed get ignorePointerEvents() {
- return this.props.pointerEvents === "none" ||
- (this.Document._isBackground && !this.isSelected() && !SnappingManager.GetIsDragging()) ||
- (this.Document.type === DocumentType.INK && Doc.GetSelectedTool() !== InkTool.None);
+ @computed get pointerEvents() {
+ if (this.props.pointerEvents === "none") return "none";
+ return this.props.styleProvider?.(this.Document, this.props.renderDepth, this.isSelected() ? "pointerEvents:selected" : "pointerEvents", this.props.layerProvider);
}
@undoBatch
@action
@@ -1091,22 +1086,13 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
}), 400);
});
- renderLock() {
- return (this.Document._isBackground !== undefined || this.isSelected(false)) &&
- ((this.Document.type === DocumentType.COL && this.Document._viewType !== CollectionViewType.Pile) || this.Document.type === DocumentType.IMG) &&
- this.props.renderDepth > 0 && !this.props.treeViewDoc ?
- <div className="documentView-lock" onClick={this.toggleBackground}>
- <FontAwesomeIcon icon={this.Document._isBackground ? "unlock" : "lock"} style={{ color: this.Document._isBackground ? "red" : undefined }} size="lg" />
- </div>
- : (null);
- }
render() {
TraceMobx();
if (!(this.props.Document instanceof Doc)) return (null);
if (GetEffectiveAcl(this.props.Document[DataSym]) === AclPrivate) return (null);
- if (this.props.Document.hidden) return (null);
- const backgroundColor = Doc.UserDoc().renderStyle === "comic" ? undefined : this.props.forcedBackgroundColor?.(this.Document) || StrCast(this.layoutDoc._backgroundColor) || StrCast(this.layoutDoc.backgroundColor) || StrCast(this.Document.backgroundColor) || this.props.backgroundColor?.(this.Document, this.props.renderDepth);
+ if (this.props.styleProvider?.(this.layoutDoc, this.props.renderDepth, "hidden", this.props.layerProvider)) return null;
+ const backgroundColor = this.props.styleProvider?.(this.layoutDoc, this.props.renderDepth, "backgroundColor", this.props.layerProvider);
const opacity = Cast(this.layoutDoc._opacity, "number", Cast(this.layoutDoc.opacity, "number", Cast(this.Document.opacity, "number", null)));
const finalOpacity = this.props.opacity ? this.props.opacity() : opacity;
const finalColor = this.layoutDoc.type === DocumentType.FONTICON || this.layoutDoc._viewType === CollectionViewType.Linear ? undefined : backgroundColor;
@@ -1120,7 +1106,7 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
let highlighting = fullDegree && this.layoutDoc.type !== DocumentType.FONTICON && this.layoutDoc._viewType !== CollectionViewType.Linear && this.props.Document.type !== DocumentType.INK;
highlighting = highlighting && this.props.focus !== emptyFunction && this.layoutDoc.title !== "[pres element template]"; // bcz: hack to turn off highlighting onsidebar panel documents. need to flag a document as not highlightable in a more direct way
const topmost = this.topMost ? "-topmost" : "";
- return <div className={`documentView-node${topmost}`}
+ return this.props.styleProvider?.(this.rootDoc, this.props.renderDepth, "docContents", this.props.layerProvider) ?? <div className={`documentView-node${topmost}`}
id={this.props.Document[Id]}
ref={this._mainCont} onKeyDown={this.onKeyDown}
onContextMenu={this.onContextMenu} onPointerDown={this.onPointerDown} onClick={this.onClick}
@@ -1142,12 +1128,12 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
transformOrigin: this._animateScalingTo ? "center center" : undefined,
transform: this._animateScalingTo ? `scale(${this._animateScalingTo})` : undefined,
transition: !this._animateScalingTo ? StrCast(this.Document.dataTransition) : `transform 0.5s ease-${this._animateScalingTo < 1 ? "in" : "out"}`,
- pointerEvents: this.ignorePointerEvents ? "none" : undefined,
+ pointerEvents: this.pointerEvents as any,
color: StrCast(this.layoutDoc.color, "inherit"),
outline: highlighting && !borderRounding ? `${highlightColors[fullDegree]} ${highlightStyles[fullDegree]} ${localScale}px` : "solid 0px",
border: highlighting && borderRounding && highlightStyles[fullDegree] === "dashed" ? `${highlightStyles[fullDegree]} ${highlightColors[fullDegree]} ${localScale}px` : undefined,
boxShadow: highlighting && borderRounding && highlightStyles[fullDegree] !== "dashed" ? `0 0 0 ${localScale}px ${highlightColors[fullDegree]}` :
- this.Document.isLinkButton && !this.props.dontRegisterView && this.props.forcedBackgroundColor?.(this.Document) !== "transparent" ?
+ this.Document.isLinkButton && !this.props.dontRegisterView && !this.props.forceHideLinkButton?.() ?
StrCast(this.layoutDoc._linkButtonShadow, "lightblue 0em 0em 1em") :
this.props.Document.isTemplateForField ? "black 0.2vw 0.2vw 0.8vw" :
undefined,
@@ -1158,10 +1144,10 @@ export class DocumentView extends DocComponent<DocumentViewProps, Document>(Docu
}}>
{this.onClickHandler && this.props.ContainingCollectionView?.props.Document._viewType === CollectionViewType.Time ? <>
{this.innards}
- <div className="documentView-contentBlocker" />
+ <div className="documentView-conentBlocker" />
</> :
this.innards}
- {this.renderLock()}
+ {!this.props.treeViewDoc && this.props.styleProvider?.(this.rootDoc, this.props.renderDepth, this.isSelected() ? "decorations:selected" : "decorations", this.props.layerProvider) || (null)}
</div>;
}
}
diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx
index 79947c023..9df3e6b81 100644
--- a/src/client/views/nodes/FieldView.tsx
+++ b/src/client/views/nodes/FieldView.tsx
@@ -26,6 +26,8 @@ export interface FieldViewProps {
Document: Doc;
DataDoc?: Doc;
LibraryPath: Doc[];
+ layerProvider?: (doc: Doc, assign?: boolean) => boolean;
+ contentsActive?: (setActive: () => boolean) => void;
onClick?: () => ScriptField;
dropAction: dropActionType;
backgroundHalo?: () => boolean;
@@ -41,9 +43,10 @@ export interface FieldViewProps {
pinToPres: (document: Doc) => void;
removeDocument?: (document: Doc | Doc[]) => boolean;
moveDocument?: (document: Doc | Doc[], targetCollection: Doc | undefined, addDocument: (document: Doc | Doc[]) => boolean) => boolean;
- backgroundColor?: (document: Opt<Doc>, renderDepth: number) => string | undefined;
+ styleProvider?: (document: Opt<Doc>, renderDepth: number, property: string, layerProvider?: (doc: Doc, assign?: boolean) => boolean) => any;
ScreenToLocalTransform: () => Transform;
bringToFront: (doc: Doc, sendToBack?: boolean) => void;
+ parentActive: (outsideReaction: boolean) => boolean;
active: (outsideReaction?: boolean) => boolean;
whenActiveChanged: (isActive: boolean) => void;
LayoutTemplateString?: string;
diff --git a/src/client/views/nodes/FilterBox.tsx b/src/client/views/nodes/FilterBox.tsx
index 6f01e5916..ab401213c 100644
--- a/src/client/views/nodes/FilterBox.tsx
+++ b/src/client/views/nodes/FilterBox.tsx
@@ -161,7 +161,7 @@ export class FilterBox extends ViewBoxBaseComponent<FieldViewProps, FilterBoxDoc
}
render() {
- const facetCollection = this.props.Document.proto as Doc;
+ const facetCollection = this.props.Document as Doc;
const flyout = <div className="filterBox-flyout" style={{ width: `100%`, height: this.props.PanelHeight() - 30 }} onWheel={e => e.stopPropagation()}>
{this._allFacets.map(facet => <label className="filterBox-flyout-facet" key={`${facet}`} onClick={e => this.facetClick(facet)}>
<input type="checkbox" onChange={e => { }} checked={DocListCast(this.props.Document[this.props.fieldKey]).some(d => d.title === facet)} />
@@ -204,6 +204,7 @@ export class FilterBox extends ViewBoxBaseComponent<FieldViewProps, FilterBoxDoc
select={returnFalse}
bringToFront={emptyFunction}
active={this.props.active}
+ parentActive={returnFalse}
whenActiveChanged={returnFalse}
treeViewHideTitle={true}
ContentScaling={returnOne}
@@ -213,7 +214,7 @@ export class FilterBox extends ViewBoxBaseComponent<FieldViewProps, FilterBoxDoc
ignoreFields={this.ignoreFields}
annotationsKey={""}
dontRegisterView={true}
- backgroundColor={this.filterBackground}
+ styleProvider={this.filterBackground}
moveDocument={returnFalse}
removeDocument={returnFalse}
addDocument={returnFalse} />
diff --git a/src/client/views/nodes/FontIconBox.tsx b/src/client/views/nodes/FontIconBox.tsx
index 276c66bb1..dfbd89c88 100644
--- a/src/client/views/nodes/FontIconBox.tsx
+++ b/src/client/views/nodes/FontIconBox.tsx
@@ -61,7 +61,7 @@ export class FontIconBox extends DocComponent<FieldViewProps, FontIconDocument>(
render() {
const label = StrCast(this.rootDoc.label, StrCast(this.rootDoc.title));
const color = StrCast(this.layoutDoc.color, this._foregroundColor);
- const backgroundColor = StrCast(this.layoutDoc._backgroundColor, StrCast(this.rootDoc.backgroundColor, this.props.backgroundColor?.(this.rootDoc, this.props.renderDepth)));
+ const backgroundColor = this.props.styleProvider?.(this.rootDoc, this.props.renderDepth, "backgroundColor", this.props.layerProvider);
const shape = StrCast(this.layoutDoc.iconShape, label ? "round" : "circle");
const icon = StrCast(this.dataDoc.icon, "user") as any;
const presSize = shape === 'round' ? 25 : 30;
diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx
index 88dc3b241..1c1a13061 100644
--- a/src/client/views/nodes/ImageBox.tsx
+++ b/src/client/views/nodes/ImageBox.tsx
@@ -161,7 +161,6 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps, ImageD
if (field) {
const funcs: ContextMenuProps[] = [];
funcs.push({ description: "Rotate Clockwise 90", event: this.rotate, icon: "expand-arrows-alt" });
- funcs.push({ description: "Make Background", event: () => { this.layoutDoc._isBackground = true; this.props.bringToFront?.(this.rootDoc); }, icon: "expand-arrows-alt" });
if (!Doc.UserDoc().noviceMode) {
funcs.push({ description: "Export to Google Photos", event: () => GooglePhotos.Transactions.UploadImages([this.props.Document]), icon: "caret-square-right" });
funcs.push({ description: "Copy path", event: () => Utils.CopyText(field.url.href), icon: "expand-arrows-alt" });
@@ -411,7 +410,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps, ImageD
transform: this.props.PanelWidth() ? undefined : `scale(${this.contentScaling})`,
width: this.props.PanelWidth() ? undefined : `${100 / this.contentScaling}%`,
height: this.props.PanelWidth() ? undefined : `${100 / this.contentScaling}%`,
- pointerEvents: this.layoutDoc._isBackground ? "none" : undefined,
+ pointerEvents: this.props.layerProvider?.(this.layoutDoc) === false ? "none" : undefined,
borderRadius: `${Number(StrCast(this.layoutDoc.borderRounding).replace("px", "")) / this.contentScaling}px`
}} >
<CollectionFreeFormView {...OmitKeys(this.props, ["NativeWidth", "NativeHeight"]).omit}
diff --git a/src/client/views/nodes/KeyValueBox.tsx b/src/client/views/nodes/KeyValueBox.tsx
index c5ff42a1a..4ac932c24 100644
--- a/src/client/views/nodes/KeyValueBox.tsx
+++ b/src/client/views/nodes/KeyValueBox.tsx
@@ -70,7 +70,7 @@ export class KeyValueBox extends React.Component<FieldViewProps> {
public static ApplyKVPScript(doc: Doc, key: string, kvpScript: KVPScript, forceOnDelegate?: boolean): boolean {
const { script, type, onDelegate } = kvpScript;
//const target = onDelegate ? Doc.Layout(doc.layout) : Doc.GetProto(doc); // bcz: TODO need to be able to set fields on layout templates
- const target = forceOnDelegate || onDelegate ? doc : Doc.GetProto(doc);
+ const target = forceOnDelegate || onDelegate ? doc : doc.proto || doc;
let field: Field;
if (type === "computed") {
field = new ComputedField(script);
diff --git a/src/client/views/nodes/KeyValuePair.tsx b/src/client/views/nodes/KeyValuePair.tsx
index 2e2319447..5e1f8fcea 100644
--- a/src/client/views/nodes/KeyValuePair.tsx
+++ b/src/client/views/nodes/KeyValuePair.tsx
@@ -68,6 +68,7 @@ export class KeyValuePair extends React.Component<KeyValuePairProps> {
dropAction: "alias",
bringToFront: emptyFunction,
renderDepth: 1,
+ parentActive: returnFalse,
active: returnFalse,
whenActiveChanged: emptyFunction,
ScreenToLocalTransform: Transform.Identity,
diff --git a/src/client/views/nodes/LinkAnchorBox.tsx b/src/client/views/nodes/LinkAnchorBox.tsx
index ec8c43ab4..7ce9abf27 100644
--- a/src/client/views/nodes/LinkAnchorBox.tsx
+++ b/src/client/views/nodes/LinkAnchorBox.tsx
@@ -92,7 +92,7 @@ export class LinkAnchorBox extends ViewBoxBaseComponent<FieldViewProps, LinkAnch
openLinkTargetOnRight = (e: React.MouseEvent) => {
const alias = Doc.MakeAlias(Cast(this.layoutDoc[this.fieldKey], Doc, null));
alias.isLinkButton = undefined;
- alias._isBackground = undefined;
+ alias.layers = undefined;
alias.layoutKey = "layout";
this.props.addDocTab(alias, "add:right");
}
diff --git a/src/client/views/nodes/LinkBox.tsx b/src/client/views/nodes/LinkBox.tsx
index 64ae1051b..913c07eb2 100644
--- a/src/client/views/nodes/LinkBox.tsx
+++ b/src/client/views/nodes/LinkBox.tsx
@@ -17,7 +17,7 @@ export class LinkBox extends ViewBoxBaseComponent<FieldViewProps, LinkDocument>(
public static LayoutString(fieldKey: string) { return FieldView.LayoutString(LinkBox, fieldKey); }
render() {
return <div className={`linkBox-container${this.active() ? "-interactive" : ""}`}
- style={{ background: this.props.backgroundColor?.(this.props.Document, this.props.renderDepth) }} >
+ style={{ background: this.props.styleProvider?.(this.props.Document, this.props.renderDepth, "backgroundColor", this.props.layerProvider) }} >
<CollectionTreeView {...this.props}
ChromeHeight={returnZero}
diff --git a/src/client/views/nodes/LinkDocPreview.tsx b/src/client/views/nodes/LinkDocPreview.tsx
index d47942bd9..dfdca7ebb 100644
--- a/src/client/views/nodes/LinkDocPreview.tsx
+++ b/src/client/views/nodes/LinkDocPreview.tsx
@@ -16,7 +16,7 @@ interface Props {
linkDoc?: Doc;
linkSrc?: Doc;
href?: string;
- backgroundColor: (doc: Opt<Doc>, renderDepth: number) => string;
+ styleProvider?: (doc: Opt<Doc>, renderDepth: number, property: string, layerProvider?: (doc: Doc, assign?: boolean) => boolean) => any;
addDocTab: (document: Doc, where: string) => boolean;
location: number[];
}
@@ -112,7 +112,7 @@ export class LinkDocPreview extends React.Component<Props> {
whenActiveChanged={returnFalse}
bringToFront={returnFalse}
ContentScaling={returnOne}
- backgroundColor={this.props.backgroundColor} />;
+ styleProvider={this.props.styleProvider} />;
}
render() {
diff --git a/src/client/views/nodes/PresBox.tsx b/src/client/views/nodes/PresBox.tsx
index 683cb938a..455ee87e1 100644
--- a/src/client/views/nodes/PresBox.tsx
+++ b/src/client/views/nodes/PresBox.tsx
@@ -640,7 +640,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
removeDocument = (doc: Doc) => Doc.RemoveDocFromList(this.dataDoc, this.fieldKey, doc);
getTransform = () => this.props.ScreenToLocalTransform().translate(-5, -65);// listBox padding-left and pres-box-cont minHeight
panelHeight = () => this.props.PanelHeight() - 40;
- active = (outsideReaction?: boolean) => ((Doc.GetSelectedTool() === InkTool.None && !this.layoutDoc._isBackground) &&
+ active = (outsideReaction?: boolean) => ((Doc.GetSelectedTool() === InkTool.None && this.props.layerProvider?.(this.layoutDoc) !== false) &&
(this.layoutDoc.forceActive || this.props.isSelected(outsideReaction) || this._isChildActive || this.props.renderDepth === 0) ? true : false)
/**
diff --git a/src/client/views/nodes/ScriptingBox.scss b/src/client/views/nodes/ScriptingBox.scss
index a937364a8..8d76f2b1d 100644
--- a/src/client/views/nodes/ScriptingBox.scss
+++ b/src/client/views/nodes/ScriptingBox.scss
@@ -213,12 +213,12 @@
.scriptingBox-button {
font-size: xx-small;
- width: 50%;
+ width: 33%;
resize: auto;
}
- .scriptingBox-button-third {
- width: 33%;
+ .scriptingBox-button-finish {
+ width: 25%;
}
}
} \ No newline at end of file
diff --git a/src/client/views/nodes/ScriptingBox.tsx b/src/client/views/nodes/ScriptingBox.tsx
index 1a5edc1d9..f1f2cd7d3 100644
--- a/src/client/views/nodes/ScriptingBox.tsx
+++ b/src/client/views/nodes/ScriptingBox.tsx
@@ -628,13 +628,13 @@ export class ScriptingBox extends ViewBoxAnnotatableComponent<FieldViewProps, Sc
// toolbar (with compile and apply buttons) for scripting UI
renderScriptingTools() {
- const buttonStyle = "scriptingBox-button" + (this.rootDoc.layoutKey === "layout_onClick" ? "third" : "");
+ const buttonStyle = "scriptingBox-button" + (StrCast(this.rootDoc.layoutKey).startsWith("layout_on") ? "-finish" : "");
return <div className="scriptingBox-toolbar">
- <button className={buttonStyle} style={{ width: "33%" }} onPointerDown={e => { this.onCompile(); e.stopPropagation(); }}>Compile</button>
- <button className={buttonStyle} style={{ width: "33%" }} onPointerDown={e => { this.onApply(); e.stopPropagation(); }}>Apply</button>
- <button className={buttonStyle} style={{ width: "33%" }} onPointerDown={e => { this.onSave(); e.stopPropagation(); }}>Save</button>
+ <button className={buttonStyle} onPointerDown={e => { this.onCompile(); e.stopPropagation(); }}>Compile</button>
+ <button className={buttonStyle} onPointerDown={e => { this.onApply(); e.stopPropagation(); }}>Apply</button>
+ <button className={buttonStyle} onPointerDown={e => { this.onSave(); e.stopPropagation(); }}>Save</button>
- {this.rootDoc.layoutKey !== "layout_onClick" ? (null) :
+ {!StrCast(this.rootDoc.layoutKey).startsWith("layout_on") ? (null) : // onClick, onChecked, etc need a Finish button to return to their default layout
<button className={buttonStyle} onPointerDown={e => { this.onFinish(); e.stopPropagation(); }}>Finish</button>}
</div>;
}
@@ -662,11 +662,11 @@ export class ScriptingBox extends ViewBoxAnnotatableComponent<FieldViewProps, Sc
// toolbar (with edit and run buttons and error message) for params UI
renderTools(toolSet: string, func: () => void) {
- const buttonStyle = "scriptingBox-button" + (this.rootDoc.layoutKey === "layout_onClick" ? "third" : "");
+ const buttonStyle = "scriptingBox-button" + (StrCast(this.rootDoc.layoutKey).startsWith("layout_on") ? "-finish" : "");
return <div className="scriptingBox-toolbar">
<button className={buttonStyle} onPointerDown={e => { this.onEdit(); e.stopPropagation(); }}>Edit</button>
<button className={buttonStyle} onPointerDown={e => { func(); e.stopPropagation(); }}>{toolSet}</button>
- {this.rootDoc.layoutKey !== "layout_onClick" ? (null) :
+ {!StrCast(this.rootDoc.layoutKey).startsWith("layout_on") ? (null) :
<button className={buttonStyle} onPointerDown={e => { this.onFinish(); e.stopPropagation(); }}>Finish</button>}
</div>;
}
diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx
index bc69a3954..8ce76a347 100644
--- a/src/client/views/nodes/VideoBox.tsx
+++ b/src/client/views/nodes/VideoBox.tsx
@@ -393,7 +393,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent<FieldViewProps, VideoD
transform: this.props.PanelWidth() ? undefined : `scale(${this.contentScaling})`,
width: this.props.PanelWidth() ? undefined : `${100 / this.contentScaling}%`,
height: this.props.PanelWidth() ? undefined : `${100 / this.contentScaling}%`,
- pointerEvents: this.layoutDoc._isBackground ? "none" : undefined,
+ pointerEvents: this.props.layerProvider?.(this.layoutDoc) === false ? "none" : undefined,
borderRadius: `${Number(StrCast(this.layoutDoc.borderRounding).replace("px", "")) / this.contentScaling}px`
}} >
<div className="videoBox-viewer" >
diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx
index 80e2d3ce2..9a1ae336f 100644
--- a/src/client/views/nodes/WebBox.tsx
+++ b/src/client/views/nodes/WebBox.tsx
@@ -193,7 +193,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps, WebDocum
this.layoutDoc._height = this.layoutDoc[WidthSym]() / youtubeaspect;
}
} // else it's an HTMLfield
- } else if (field?.url) {
+ } else if (field?.url && !this.dataDoc.text) {
const result = await WebRequest.get(Utils.CorsProxy(field.url.href));
if (result) {
this.dataDoc.text = htmlToText.fromString(result.content);
@@ -442,7 +442,8 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps, WebDocum
view = <iframe className="webBox-iframe" enable-annotation={"true"} ref={action((r: HTMLIFrameElement | null) => this._iframe = r)} src={url} onLoad={this.iframeLoaded}
// the 'allow-top-navigation' and 'allow-top-navigation-by-user-activation' attributes are left out to prevent iframes from redirecting the top-level Dash page
- sandbox={"allow-forms allow-modals allow-orientation-lock allow-pointer-lock allow-popups allow-popups-to-escape-sandbox allow-presentation allow-same-origin allow-scripts"} />;
+ // sandbox={"allow-forms allow-modals allow-orientation-lock allow-pointer-lock allow-popups allow-popups-to-escape-sandbox allow-presentation allow-same-origin allow-scripts"} />;
+ sandbox={"allow-forms allow-modals allow-orientation-lock allow-pointer-lock allow-popups allow-popups-to-escape-sandbox allow-presentation allow-same-origin"} />;
} else {
view = <iframe className="webBox-iframe" enable-annotation={"true"} ref={action((r: HTMLIFrameElement | null) => this._iframe = r)} src={"https://crossorigin.me/https://cs.brown.edu"} />;
}
@@ -461,7 +462,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps, WebDocum
{view}
</div>
{!frozen ? (null) :
- <div className="webBox-overlay" style={{ pointerEvents: this.layoutDoc._isBackground ? undefined : "all" }}
+ <div className="webBox-overlay" style={{ pointerEvents: this.props.layerProvider?.(this.layoutDoc) === false ? undefined : "all" }}
onWheel={this.onPreWheel} onPointerDown={this.onPrePointer} onPointerMove={this.onPrePointer} onPointerUp={this.onPrePointer}>
<div className="touch-iframe-overlay" onPointerDown={this.onLongPressDown} >
<div className="indicator" ref={this._iframeIndicatorRef}></div>
@@ -663,7 +664,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps, WebDocum
transform: `scale(${scaling})`,
width: `${100 / scaling}% `,
height: `${100 / scaling}% `,
- pointerEvents: this.layoutDoc._isBackground ? "none" : undefined
+ pointerEvents: this.props.layerProvider?.(this.layoutDoc) === false ? "none" : undefined
}}
onContextMenu={this.specificContextMenu}>
<base target="_blank" />
@@ -671,7 +672,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps, WebDocum
<div className={"webBox-outerContent"} ref={this._outerRef}
style={{
width: `${Math.max(100, 100 / scaling)}% `,
- pointerEvents: this.layoutDoc.isAnnotating && !this.layoutDoc._isBackground ? "all" : "none"
+ pointerEvents: this.layoutDoc.isAnnotating && this.props.layerProvider?.(this.layoutDoc) !== false ? "all" : "none"
}}
onWheel={e => {
const target = this._outerRef.current;
@@ -693,7 +694,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps, WebDocum
>
<div className={"webBox-innerContent"} style={{
height: NumCast(this.scrollHeight, 50),
- pointerEvents: this.layoutDoc._isBackground ? "none" : undefined
+ pointerEvents: this.props.layerProvider?.(this.layoutDoc) === false ? "none" : undefined
}}>
<CollectionFreeFormView {...OmitKeys(this.props, ["NativeWidth", "NativeHeight"]).omit}
PanelHeight={this.props.PanelHeight}
diff --git a/src/client/views/nodes/formattedText/DashDocView.tsx b/src/client/views/nodes/formattedText/DashDocView.tsx
index 7cd92b8b9..67bfd435b 100644
--- a/src/client/views/nodes/formattedText/DashDocView.tsx
+++ b/src/client/views/nodes/formattedText/DashDocView.tsx
@@ -240,7 +240,7 @@ export class DashDocView extends React.Component<IDashDocView> {
PanelWidth={finalLayout[WidthSym]}
PanelHeight={finalLayout[HeightSym]}
focus={this.outerFocus}
- backgroundColor={returnEmptyString}
+ styleProvider={returnEmptyString}
parentActive={returnFalse}
whenActiveChanged={returnFalse}
bringToFront={emptyFunction}
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.scss b/src/client/views/nodes/formattedText/FormattedTextBox.scss
index b75cc230f..b04f60500 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.scss
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.scss
@@ -113,6 +113,9 @@
.ProseMirror {
padding:10px;
}
+}
+.formattedTextBox-outer-selected {
+
.ProseMirror:hover {
background: unset;
}
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index fe38939c5..5017d21f1 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -810,7 +810,13 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
this.dataDoc[UpdatingFromServer] = this.dataDoc[ForceServerWrite] = false;
}
}
+
+ IsActive = () => {
+ return this.active();//this.props.isSelected() || this._isChildActive || this.props.renderDepth === 0;
+ }
+
componentDidMount() {
+ this.props.contentsActive?.(this.IsActive);
this._cachedLinks = DocListCast(this.Document.links);
this._disposers.sidebarheight = reaction(
() => ({ annoHeight: NumCast(this.rootDoc[this.annotationKey + "-height"]), textHeight: NumCast(this.rootDoc[this.fieldKey + "-height"]) }),
@@ -1616,13 +1622,13 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
const active = this.active();
const scale = this.props.hideOnLeave ? 1 : this.props.ContentScaling() * NumCast(this.layoutDoc._viewScale, 1);
const rounded = StrCast(this.layoutDoc.borderRounding) === "100%" ? "-rounded" : "";
- const interactive = (Doc.GetSelectedTool() === InkTool.None || SnappingManager.GetIsDragging()) && !this.layoutDoc._isBackground;
+ const interactive = (Doc.GetSelectedTool() === InkTool.None || SnappingManager.GetIsDragging()) && (this.layoutDoc.z || this.props.layerProvider?.(this.layoutDoc) !== false);
if (!selected && FormattedTextBoxComment.textBox === this) setTimeout(() => FormattedTextBoxComment.Hide());
const minimal = this.props.ignoreAutoHeight;
const margins = NumCast(this.layoutDoc._yMargin, this.props.yMargin || 0);
const selPad = Math.min(margins, 10);
const padding = Math.max(margins + ((selected && !this.layoutDoc._singleLine) || minimal ? -selPad : 0), 0);
- const selclass = selected && !this.layoutDoc._singleLine && margins >= 10 ? "-selected" : "";
+ const selPaddingClass = selected && !this.layoutDoc._singleLine && margins >= 10 ? "-selected" : "";
return (
<div className="formattedTextBox-cont" ref={this._boxRef}
style={{
@@ -1665,12 +1671,15 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
})}
onDoubleClick={this.onDoubleClick}
>
- <div className={`formattedTextBox-outer${selclass}`} ref={this._scrollRef}
- style={{ width: `calc(100% - ${this.sidebarWidthPercent})`, pointerEvents: !active && !SnappingManager.GetIsDragging() ? "none" : undefined }}
+ <div className={`formattedTextBox-outer${selected ? "-selected" : ""}`} ref={this._scrollRef}
+ style={{
+ width: `calc(100% - ${this.sidebarWidthPercent})`,
+ pointerEvents: !active && !SnappingManager.GetIsDragging() ? "none" : undefined,
+ overflow: this.layoutDoc._singleLine ? "hidden" : undefined,
+ }}
onScroll={this.onscrolled} onDrop={this.ondrop} >
- <div className={minimal ? "formattedTextBox-minimal" : `formattedTextBox-inner${rounded}${selclass}`} ref={this.createDropTarget}
+ <div className={minimal ? "formattedTextBox-minimal" : `formattedTextBox-inner${rounded}${selPaddingClass}`} ref={this.createDropTarget}
style={{
- overflow: this.layoutDoc._singleLine ? "hidden" : undefined,
padding: this.layoutDoc._textBoxPadding ? StrCast(this.layoutDoc._textBoxPadding) : `${padding}px`,
pointerEvents: !active && !SnappingManager.GetIsDragging() ? ((this.layoutDoc.isLinkButton || this.props.onClick) ? "none" : undefined) : undefined
}}
diff --git a/src/client/views/nodes/formattedText/RichTextSchema.tsx b/src/client/views/nodes/formattedText/RichTextSchema.tsx
index 40c1d1cac..b5d984aac 100644
--- a/src/client/views/nodes/formattedText/RichTextSchema.tsx
+++ b/src/client/views/nodes/formattedText/RichTextSchema.tsx
@@ -148,7 +148,7 @@ export class DashDocView {
PanelWidth={finalLayout[WidthSym]}
PanelHeight={finalLayout[HeightSym]}
focus={this.outerFocus}
- backgroundColor={returnEmptyString}
+ styleProvider={returnEmptyString}
parentActive={returnFalse}
whenActiveChanged={returnFalse}
bringToFront={emptyFunction}
diff --git a/src/client/views/nodes/formattedText/marks_rts.ts b/src/client/views/nodes/formattedText/marks_rts.ts
index cca7ea013..ea239e4d3 100644
--- a/src/client/views/nodes/formattedText/marks_rts.ts
+++ b/src/client/views/nodes/formattedText/marks_rts.ts
@@ -41,7 +41,7 @@ export const marks: { [index: string]: MarkSpec } = {
return node.attrs.docref && node.attrs.title ?
["div", ["span", `"`], ["span", 0], ["span", `"`], ["br"], ["a", { ...node.attrs, href: node.attrs.allLinks[0].href, class: "prosemirror-attribution" }, node.attrs.title], ["br"]] :
//node.attrs.allLinks.length === 1 ?
- ["a", { ...node.attrs, class: linkids, "data-targetids": targetids, "data-targethrefs": targethrefs, title: `${node.attrs.title}`, href: node.attrs.allLinks[0].href, style: `text-decoration: ${linkids === " " ? "underline" : undefined}` }, 0];
+ ["a", { ...node.attrs, class: linkids, "data-targetids": targetids, "data-targethrefs": targethrefs, title: `${node.attrs.title}`, href: node.attrs.allLinks[0]?.href, style: `text-decoration: ${linkids === " " ? "underline" : undefined}` }, 0];
// ["div", { class: "prosemirror-anchor" },
// ["span", { class: "prosemirror-linkBtn" },
// ["a", { ...node.attrs, class: linkids, "data-targetids": targetids, title: `${node.attrs.title}` }, 0],