aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/collections
diff options
context:
space:
mode:
authorSam Wilkins <abdullah_ahmed@brown.edu>2019-04-13 19:14:42 -0400
committerSam Wilkins <abdullah_ahmed@brown.edu>2019-04-13 19:14:42 -0400
commit7a1a028d1d3f5602d39f559cb1614abda658a371 (patch)
tree5de71b963a2e2e370818591f6e99fba868503ee0 /src/client/views/collections
parent35f09470b2939a6640b85c94a9a4ea2551a6ea42 (diff)
parentb7252aeacbbd73120bc6f80d551f4505646a883b (diff)
resolved merge conflicts with master
Diffstat (limited to 'src/client/views/collections')
-rw-r--r--src/client/views/collections/CollectionBaseView.tsx17
-rw-r--r--src/client/views/collections/CollectionDockingView.scss21
-rw-r--r--src/client/views/collections/CollectionDockingView.tsx102
-rw-r--r--src/client/views/collections/CollectionSchemaView.scss6
-rw-r--r--src/client/views/collections/CollectionSchemaView.tsx28
-rw-r--r--src/client/views/collections/CollectionSubView.tsx51
-rw-r--r--src/client/views/collections/CollectionTreeView.scss6
-rw-r--r--src/client/views/collections/CollectionTreeView.tsx8
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx22
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormRemoteCursors.scss2
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss20
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx63
-rw-r--r--src/client/views/collections/collectionFreeForm/MarqueeView.scss2
-rw-r--r--src/client/views/collections/collectionFreeForm/MarqueeView.tsx45
-rw-r--r--src/client/views/collections/collectionFreeForm/PreviewCursor.scss27
-rw-r--r--src/client/views/collections/collectionFreeForm/PreviewCursor.tsx120
16 files changed, 237 insertions, 303 deletions
diff --git a/src/client/views/collections/CollectionBaseView.tsx b/src/client/views/collections/CollectionBaseView.tsx
index 4380c8194..b5eaab349 100644
--- a/src/client/views/collections/CollectionBaseView.tsx
+++ b/src/client/views/collections/CollectionBaseView.tsx
@@ -32,19 +32,18 @@ export interface CollectionViewProps extends FieldViewProps {
contentRef?: React.Ref<HTMLDivElement>;
}
-export const COLLECTION_BORDER_WIDTH = 1;
@observer
export class CollectionBaseView extends React.Component<CollectionViewProps> {
- get collectionViewType(): CollectionViewType {
+ get collectionViewType(): CollectionViewType | undefined {
let Document = this.props.Document;
let viewField = Document.GetT(KeyStore.ViewType, NumberField);
if (viewField === FieldWaiting) {
- return CollectionViewType.Invalid;
+ return undefined;
} else if (viewField) {
return viewField.Data;
} else {
- return CollectionViewType.Freeform;
+ return CollectionViewType.Invalid;
}
}
@@ -107,15 +106,18 @@ export class CollectionBaseView extends React.Component<CollectionViewProps> {
const field = new ListField([doc]);
// const script = CompileScript(`
// if(added) {
- // console.log("added " + field.Title);
+ // console.log("added " + field.Title + " " + doc.Title);
// } else {
- // console.log("removed " + field.Title);
+ // console.log("removed " + field.Title + " " + doc.Title);
// }
// `, {
// addReturn: false,
// params: {
// field: Document.name,
// added: "boolean"
+ // },
+ // capturedVariables: {
+ // doc: this.props.Document
// }
// });
// if (script.compiled) {
@@ -177,9 +179,10 @@ export class CollectionBaseView extends React.Component<CollectionViewProps> {
active: this.active,
onActiveChanged: this.onActiveChanged,
};
+ const viewtype = this.collectionViewType;
return (
<div className={this.props.className || "collectionView-cont"} onContextMenu={this.props.onContextMenu} ref={this.props.contentRef}>
- {this.props.children(this.collectionViewType, props)}
+ {viewtype !== undefined ? this.props.children(viewtype, props) : (null)}
</div>
);
}
diff --git a/src/client/views/collections/CollectionDockingView.scss b/src/client/views/collections/CollectionDockingView.scss
index 583d50c5b..0e7e0afa7 100644
--- a/src/client/views/collections/CollectionDockingView.scss
+++ b/src/client/views/collections/CollectionDockingView.scss
@@ -1,8 +1,29 @@
+@import "../../views/globalCssVariables.scss";
+
.collectiondockingview-content {
height: 100%;
}
+.lm_active .messageCounter{
+ color:white;
+ background: #999999;
+}
+.messageCounter {
+ width:18px;
+ height:20px;
+ text-align: center;
+ border-radius: 20px;
+ margin-left: 5px;
+ transform: translate(0px, -8px);
+ display: inline-block;
+ background: transparent;
+ border: 1px #999999 solid;
+}
.collectiondockingview-container {
+ width: 100%;
+ height: 100%;
+ border-style: solid;
+ border-width: $COLLECTION_BORDER_WIDTH;
position: absolute;
top: 0;
left: 0;
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index 212cf8a69..eb1cd1c09 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -7,18 +7,18 @@ import * as ReactDOM from 'react-dom';
import { Document } from "../../../fields/Document";
import { KeyStore } from "../../../fields/KeyStore";
import Measure from "react-measure";
-import { FieldId, Opt, Field } from "../../../fields/Field";
-import { Utils, returnTrue, emptyFunction } from "../../../Utils";
+import { FieldId, Opt, Field, FieldWaiting } from "../../../fields/Field";
+import { Utils, returnTrue, emptyFunction, emptyDocFunction } from "../../../Utils";
import { Server } from "../../Server";
import { undoBatch } from "../../util/UndoManager";
import { DocumentView } from "../nodes/DocumentView";
import "./CollectionDockingView.scss";
-import { COLLECTION_BORDER_WIDTH } from "./CollectionBaseView";
import React = require("react");
import { SubCollectionViewProps } from "./CollectionSubView";
import { ServerUtils } from "../../../server/ServerUtil";
-import { DragManager } from "../../util/DragManager";
+import { DragManager, DragLinksAsDocuments } from "../../util/DragManager";
import { TextField } from "../../../fields/TextField";
+import { ListField } from "../../../fields/ListField";
@observer
export class CollectionDockingView extends React.Component<SubCollectionViewProps> {
@@ -194,23 +194,35 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
@action
onPointerDown = (e: React.PointerEvent): void => {
var className = (e.target as any).className;
- if ((className === "lm_title" || className === "lm_tab lm_active") && (e.ctrlKey || e.altKey)) {
+ if (className === "messageCounter") {
e.stopPropagation();
e.preventDefault();
+ let x = e.clientX;
+ let y = e.clientY;
let docid = (e.target as any).DashDocId;
let tab = (e.target as any).parentElement as HTMLElement;
- Server.GetField(docid, action((f: Opt<Field>) => {
- if (f instanceof Document) {
- DragManager.StartDocumentDrag([tab], new DragManager.DocumentDragData([f]), e.pageX, e.pageY,
- {
- handlers: {
- dragComplete: action(emptyFunction),
- },
- hideSource: false
- });
- }
- }));
- }
+ Server.GetField(docid, action(async (sourceDoc: Opt<Field>) =>
+ (sourceDoc instanceof Document) && DragLinksAsDocuments(tab, x, y, sourceDoc)));
+ } else
+ if ((className === "lm_title" || className === "lm_tab lm_active") && !e.shiftKey) {
+ e.stopPropagation();
+ e.preventDefault();
+ let x = e.clientX;
+ let y = e.clientY;
+ let docid = (e.target as any).DashDocId;
+ let tab = (e.target as any).parentElement as HTMLElement;
+ Server.GetField(docid, action((f: Opt<Field>) => {
+ if (f instanceof Document) {
+ DragManager.StartDocumentDrag([tab], new DragManager.DocumentDragData([f]), x, y,
+ {
+ handlers: {
+ dragComplete: action(emptyFunction),
+ },
+ hideSource: false
+ });
+ }
+ }));
+ }
if (className === "lm_drag_handle" || className === "lm_close" || className === "lm_maximise" || className === "lm_minimise" || className === "lm_close_tab") {
this._flush = true;
}
@@ -229,24 +241,44 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
this.stateChanged();
}
+ htmlToElement(html: string) {
+ var template = document.createElement('template');
+ html = html.trim(); // Never return a text node of whitespace as the result
+ template.innerHTML = html;
+ return template.content.firstChild;
+ }
+
tabCreated = (tab: any) => {
if (tab.hasOwnProperty("contentItem") && tab.contentItem.config.type !== "stack") {
- if (tab.titleElement[0].textContent.indexOf("-waiting") !== -1) {
- Server.GetField(tab.contentItem.config.props.documentId, action((f: Opt<Field>) => {
- if (f !== undefined && f instanceof Document) {
- f.GetTAsync(KeyStore.Title, TextField, (tfield) => {
- if (tfield !== undefined) {
- tab.titleElement[0].textContent = f.Title;
- }
- });
- }
- }));
- tab.titleElement[0].DashDocId = tab.contentItem.config.props.documentId;
- }
- tab.titleElement[0].DashDocId = tab.contentItem.config.props.documentId;
+ Server.GetField(tab.contentItem.config.props.documentId, action((f: Opt<Field>) => {
+ if (f !== undefined && f instanceof Document) {
+ f.GetTAsync(KeyStore.Title, TextField, (tfield) => {
+ if (tfield !== undefined) {
+ tab.titleElement[0].textContent = f.Title;
+ }
+ });
+ f.GetTAsync(KeyStore.LinkedFromDocs, ListField).then(lf =>
+ f.GetTAsync(KeyStore.LinkedToDocs, ListField).then(lt => {
+ let count = (lf ? lf.Data.length : 0) + (lt ? lt.Data.length : 0);
+ let counter: any = this.htmlToElement(`<div class="messageCounter">${count}</div>`);
+ tab.element.append(counter);
+ counter.DashDocId = tab.contentItem.config.props.documentId;
+ (tab as any).reactionDisposer = reaction(() => [f.GetT(KeyStore.LinkedFromDocs, ListField), f.GetT(KeyStore.LinkedToDocs, ListField)],
+ (lists) => {
+ let count = (lists.length > 0 && lists[0] && lists[0]!.Data ? lists[0]!.Data.length : 0) +
+ (lists.length > 1 && lists[1] && lists[1]!.Data ? lists[1]!.Data.length : 0);
+ counter.innerHTML = count;
+ });
+ }));
+ tab.titleElement[0].DashDocId = tab.contentItem.config.props.documentId;
+ }
+ }));
}
tab.closeElement.off('click') //unbind the current click handler
.click(function () {
+ if (tab.reactionDisposer) {
+ tab.reactionDisposer();
+ }
tab.contentItem.remove();
});
}
@@ -271,13 +303,7 @@ export class CollectionDockingView extends React.Component<SubCollectionViewProp
render() {
return (
<div className="collectiondockingview-container" id="menuContainer"
- onPointerDown={this.onPointerDown} onPointerUp={this.onPointerUp} ref={this._containerRef}
- style={{
- width: "100%",
- height: "100%",
- borderStyle: "solid",
- borderWidth: `${COLLECTION_BORDER_WIDTH}px`,
- }} />
+ onPointerDown={this.onPointerDown} onPointerUp={this.onPointerUp} ref={this._containerRef} />
);
}
}
@@ -325,7 +351,7 @@ export class DockedFrameRenderer extends React.Component<DockedFrameProps> {
selectOnLoad={false}
parentActive={returnTrue}
onActiveChanged={emptyFunction}
- focus={(doc: Document) => { }}
+ focus={emptyDocFunction}
ContainingCollectionView={undefined} />
</div>;
diff --git a/src/client/views/collections/CollectionSchemaView.scss b/src/client/views/collections/CollectionSchemaView.scss
index 9cd6c8a39..c8bfedff4 100644
--- a/src/client/views/collections/CollectionSchemaView.scss
+++ b/src/client/views/collections/CollectionSchemaView.scss
@@ -1,4 +1,4 @@
-@import "../global_variables";
+@import "../globalCssVariables";
//options menu styling
#schemaOptionsMenuBtn {
@@ -58,7 +58,9 @@ ul {
.collectionSchemaView-container {
- border: 1px solid $intermediate-color;
+ border-width: $COLLECTION_BORDER_WIDTH;
+ border-color : $intermediate-color;
+ border-style: solid;
border-radius: $border-radius;
box-sizing: border-box;
position: absolute;
diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx
index f1b3e1b8f..fdb82690a 100644
--- a/src/client/views/collections/CollectionSchemaView.tsx
+++ b/src/client/views/collections/CollectionSchemaView.tsx
@@ -2,31 +2,29 @@ import React = require("react");
import { library } from '@fortawesome/fontawesome-svg-core';
import { faCog, faPlus } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { action, computed, observable, trace, untracked } from "mobx";
+import { action, computed, observable, untracked } from "mobx";
import { observer } from "mobx-react";
import Measure from "react-measure";
import ReactTable, { CellInfo, ComponentPropsGetterR, ReactTableDefaults } from "react-table";
import "react-table/react-table.css";
import { Document } from "../../../fields/Document";
-import { Field, Opt, FieldWaiting } from "../../../fields/Field";
+import { Field, Opt } from "../../../fields/Field";
import { Key } from "../../../fields/Key";
import { KeyStore } from "../../../fields/KeyStore";
import { ListField } from "../../../fields/ListField";
+import { emptyDocFunction, emptyFunction, returnFalse } from "../../../Utils";
import { Server } from "../../Server";
-import { setupDrag } from "../../util/DragManager";
+import { SetupDrag } from "../../util/DragManager";
import { CompileScript, ToField } from "../../util/Scripting";
import { Transform } from "../../util/Transform";
+import { COLLECTION_BORDER_WIDTH } from "../../views/globalCssVariables.scss";
import { anchorPoints, Flyout } from "../DocumentDecorations";
import '../DocumentDecorations.scss';
import { EditableView } from "../EditableView";
import { DocumentView } from "../nodes/DocumentView";
import { FieldView, FieldViewProps } from "../nodes/FieldView";
import "./CollectionSchemaView.scss";
-import { CollectionView } from "./CollectionView";
import { CollectionSubView } from "./CollectionSubView";
-import { TextField } from "../../../fields/TextField";
-import { COLLECTION_BORDER_WIDTH } from "./CollectionBaseView";
-import { emptyFunction, returnFalse } from "../../../Utils";
// bcz: need to add drag and drop of rows and columns. This seems like it might work for rows: https://codesandbox.io/s/l94mn1q657
@@ -82,7 +80,7 @@ export class CollectionSchemaView extends CollectionSubView {
isTopMost: false,
selectOnLoad: false,
ScreenToLocalTransform: Transform.Identity,
- focus: emptyFunction,
+ focus: emptyDocFunction,
active: returnFalse,
onActiveChanged: emptyFunction,
};
@@ -90,7 +88,7 @@ export class CollectionSchemaView extends CollectionSubView {
<FieldView {...props} />
);
let reference = React.createRef<HTMLDivElement>();
- let onItemDown = setupDrag(reference, () => props.Document, this.props.moveDocument);
+ let onItemDown = SetupDrag(reference, () => props.Document, this.props.moveDocument);
let applyToDoc = (doc: Document, run: (args?: { [name: string]: any }) => any) => {
const res = run({ this: doc });
if (!res.success) return false;
@@ -245,13 +243,13 @@ export class CollectionSchemaView extends CollectionSubView {
this._contentScaling = r.entry.width / selected!.GetNumber(KeyStore.NativeWidth, r.entry.width);
}
+ @computed
+ get borderWidth() { return COLLECTION_BORDER_WIDTH; }
getContentScaling = (): number => this._contentScaling;
getPanelWidth = (): number => this._panelWidth;
getPanelHeight = (): number => this._panelHeight;
- getTransform = (): Transform => this.props.ScreenToLocalTransform().translate(- COLLECTION_BORDER_WIDTH - this.DIVIDER_WIDTH - this._dividerX, - COLLECTION_BORDER_WIDTH).scale(1 / this._contentScaling);
- getPreviewTransform = (): Transform => this.props.ScreenToLocalTransform().translate(- COLLECTION_BORDER_WIDTH - this.DIVIDER_WIDTH - this._dividerX - this._tableWidth, - COLLECTION_BORDER_WIDTH).scale(1 / this._contentScaling);
-
- focusDocument = (doc: Document) => { };
+ getTransform = (): Transform => this.props.ScreenToLocalTransform().translate(- this.borderWidth - this.DIVIDER_WIDTH - this._dividerX, - this.borderWidth).scale(1 / this._contentScaling);
+ getPreviewTransform = (): Transform => this.props.ScreenToLocalTransform().translate(- this.borderWidth - this.DIVIDER_WIDTH - this._dividerX - this._tableWidth, - this.borderWidth).scale(1 / this._contentScaling);
onPointerDown = (e: React.PointerEvent): void => {
if (e.button === 1 && this.props.isSelected() && !e.altKey && !e.ctrlKey && !e.metaKey) {
@@ -315,7 +313,7 @@ export class CollectionSchemaView extends CollectionSubView {
PanelWidth={this.getPanelWidth}
PanelHeight={this.getPanelHeight}
ContainingCollectionView={undefined}
- focus={this.focusDocument}
+ focus={emptyDocFunction}
parentActive={this.props.active}
onActiveChanged={this.props.onActiveChanged} /> : null}
<input value={this.previewScript} onChange={this.onPreviewScriptChange}
@@ -349,7 +347,7 @@ export class CollectionSchemaView extends CollectionSubView {
</Flyout>);
return (
- <div className="collectionSchemaView-container" onPointerDown={this.onPointerDown} onWheel={this.onWheel} ref={this._mainCont} style={{ borderWidth: `${COLLECTION_BORDER_WIDTH}px` }} >
+ <div className="collectionSchemaView-container" onPointerDown={this.onPointerDown} onWheel={this.onWheel} ref={this._mainCont}>
<div className="collectionSchemaView-dropTarget" onDrop={(e: React.DragEvent) => this.onDrop(e, {})} ref={this.createDropTarget}>
<Measure onResize={this.setTableDimensions}>
{({ measureRef }) =>
diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx
index 6a6a6c900..d91db68bb 100644
--- a/src/client/views/collections/CollectionSubView.tsx
+++ b/src/client/views/collections/CollectionSubView.tsx
@@ -166,22 +166,16 @@ export class CollectionSubView extends React.Component<SubCollectionViewProps> {
let item = e.dataTransfer.items[i];
if (item.kind === "string" && item.type.indexOf("uri") !== -1) {
let str: string;
- let prom = new Promise<string>(res =>
- e.dataTransfer.items[i].getAsString(res)).then(action((s: string) => {
- str = s;
- return rp.head(ServerUtils.prepend(RouteStore.corsProxy + "/" + s));
- })).then(res => {
- let type = res.headers["content-type"];
+ let prom = new Promise<string>(resolve => e.dataTransfer.items[i].getAsString(resolve))
+ .then(action((s: string) => rp.head(ServerUtils.prepend(RouteStore.corsProxy + "/" + (str = s)))))
+ .then(result => {
+ let type = result.headers["content-type"];
if (type) {
- this.getDocumentFromType(type, str, { ...options, width: 300, nativeWidth: 300 }).then(doc => {
- if (doc) {
- this.props.addDocument(doc, false);
- }
- });
+ this.getDocumentFromType(type, str, { ...options, width: 300, nativeWidth: 300 })
+ .then(doc => doc && this.props.addDocument(doc, false));
}
});
promises.push(prom);
- // this.props.addDocument(Documents.WebDocument(s, { ...options, width: 300, height: 300 }), false)
}
let type = item.type;
if (item.kind === "file") {
@@ -197,33 +191,30 @@ export class CollectionSubView extends React.Component<SubCollectionViewProps> {
method: 'POST',
body: formData
}).then(async (res: Response) => {
- const json = await res.json();
- json.map((file: any) => {
+ (await res.json()).map(action((file: any) => {
let path = window.location.origin + file;
- runInAction(() => {
- let docPromise = this.getDocumentFromType(type, path, { ...options, nativeWidth: 300, width: 300, title: dropFileName });
+ let docPromise = this.getDocumentFromType(type, path, { ...options, nativeWidth: 300, width: 300, title: dropFileName });
- docPromise.then(doc => runInAction(() => {
- let docs = this.props.Document.GetT(KeyStore.Data, ListField);
- if (docs !== FieldWaiting) {
- if (!docs) {
- docs = new ListField<Document>();
- this.props.Document.Set(KeyStore.Data, docs);
- }
- if (doc) {
- docs.Data.push(doc);
- }
+ docPromise.then(action((doc?: Document) => {
+ let docs = this.props.Document.GetT(KeyStore.Data, ListField);
+ if (docs !== FieldWaiting) {
+ if (!docs) {
+ docs = new ListField<Document>();
+ this.props.Document.Set(KeyStore.Data, docs);
}
- }));
- });
- });
+ if (doc) {
+ docs.Data.push(doc);
+ }
+ }
+ }));
+ }));
});
promises.push(prom);
}
}
if (promises.length) {
- Promise.all(promises).catch(emptyFunction).then(() => batch.end());
+ Promise.all(promises).finally(() => batch.end());
} else {
batch.end();
}
diff --git a/src/client/views/collections/CollectionTreeView.scss b/src/client/views/collections/CollectionTreeView.scss
index 4f940e094..8ecc5b67b 100644
--- a/src/client/views/collections/CollectionTreeView.scss
+++ b/src/client/views/collections/CollectionTreeView.scss
@@ -1,7 +1,9 @@
-@import "../global_variables";
+@import "../globalCssVariables";
.collectionTreeView-dropTarget {
- border: 0px solid transparent;
+ border-width: $COLLECTION_BORDER_WIDTH;
+ border-color: transparent;
+ border-style: solid;
border-radius: $border-radius;
box-sizing: border-box;
height: 100%;
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index 659cff9fe..51a02fc25 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -7,13 +7,13 @@ import { Document } from "../../../fields/Document";
import { FieldWaiting } from "../../../fields/Field";
import { KeyStore } from "../../../fields/KeyStore";
import { ListField } from "../../../fields/ListField";
-import { setupDrag, DragManager } from "../../util/DragManager";
+import { SetupDrag, DragManager } from "../../util/DragManager";
import { EditableView } from "../EditableView";
import "./CollectionTreeView.scss";
import { CollectionView } from "./CollectionView";
+import * as globalCssVariables from "../../views/globalCssVariables.scss";
import { CollectionSubView } from "./CollectionSubView";
import React = require("react");
-import { COLLECTION_BORDER_WIDTH } from './CollectionBaseView';
import { props } from 'bluebird';
@@ -77,7 +77,7 @@ class TreeView extends React.Component<TreeViewProps> {
*/
renderTitle() {
let reference = React.createRef<HTMLDivElement>();
- let onItemDown = setupDrag(reference, () => this.props.document, this.props.moveDocument, this.props.copyOnDrag);
+ let onItemDown = SetupDrag(reference, () => this.props.document, this.props.moveDocument, this.props.copyOnDrag);
let editableView = (titleString: string) =>
(<EditableView
display={"inline"}
@@ -139,7 +139,7 @@ export class CollectionTreeView extends CollectionSubView {
);
return (
- <div id="body" className="collectionTreeView-dropTarget" onWheel={(e: React.WheelEvent) => e.stopPropagation()} onDrop={(e: React.DragEvent) => this.onDrop(e, {})} ref={this.createDropTarget} style={{ borderWidth: `${COLLECTION_BORDER_WIDTH}px` }}>
+ <div id="body" className="collectionTreeView-dropTarget" onWheel={(e: React.WheelEvent) => e.stopPropagation()} onDrop={(e: React.DragEvent) => this.onDrop(e, {})} ref={this.createDropTarget}>
<div className="coll-title">
<EditableView
contents={this.props.Document.Title}
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx
index cf058090d..647c83d4d 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLinksView.tsx
@@ -1,4 +1,4 @@
-import { computed, reaction } from "mobx";
+import { computed, reaction, trace, IReactionDisposer } from "mobx";
import { observer } from "mobx-react";
import { Document } from "../../../../fields/Document";
import { FieldWaiting } from "../../../../fields/Field";
@@ -15,18 +15,15 @@ import React = require("react");
@observer
export class CollectionFreeFormLinksView extends React.Component<CollectionViewProps> {
- HackToAvoidReactionFiringUnnecessarily?: Document = undefined;
+ _brushReactionDisposer?: IReactionDisposer;
componentDidMount() {
- this.HackToAvoidReactionFiringUnnecessarily = this.props.Document;
- reaction(() =>
- DocumentManager.Instance.getAllDocumentViews(this.HackToAvoidReactionFiringUnnecessarily!).
- map(dv => dv.props.Document.GetNumber(KeyStore.X, 0)),
+ this._brushReactionDisposer = reaction(() => this.props.Document.GetList<Document>(this.props.fieldKey, []).map(doc => doc.GetNumber(KeyStore.X, 0)),
() => {
- let views = DocumentManager.Instance.getAllDocumentViews(this.props.Document);
+ let views = this.props.Document.GetList<Document>(this.props.fieldKey, []);
for (let i = 0; i < views.length; i++) {
for (let j = 0; j < views.length; j++) {
- let srcDoc = views[j].props.Document;
- let dstDoc = views[i].props.Document;
+ let srcDoc = views[j];
+ let dstDoc = views[i];
let x1 = srcDoc.GetNumber(KeyStore.X, 0);
let x1w = srcDoc.GetNumber(KeyStore.Width, -1);
let x2 = dstDoc.GetNumber(KeyStore.X, 0);
@@ -53,7 +50,7 @@ export class CollectionFreeFormLinksView extends React.Component<CollectionViewP
linkDoc.SetText(KeyStore.LinkDescription, "Brush between " + srcTarg.Title + " and " + dstTarg.Title);
linkDoc.SetData(KeyStore.BrushingDocs, [dstTarg, srcTarg], ListField);
- brushAction = brushAction = (field: ListField<Document>) => {
+ brushAction = (field: ListField<Document>) => {
if (findBrush(field) === -1) {
console.log("ADD BRUSH " + srcTarg.Title + " " + dstTarg.Title);
(findBrush(field) === -1) && field.Data.push(linkDoc);
@@ -67,6 +64,11 @@ export class CollectionFreeFormLinksView extends React.Component<CollectionViewP
}
});
}
+ componentWillUnmount() {
+ if (this._brushReactionDisposer) {
+ this._brushReactionDisposer();
+ }
+ }
documentAnchors(view: DocumentView) {
let equalViews = [view];
let containerDoc = view.props.Document.GetT(KeyStore.AnnotationOn, Document);
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormRemoteCursors.scss b/src/client/views/collections/collectionFreeForm/CollectionFreeFormRemoteCursors.scss
index c38787802..c5b8fc5e8 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormRemoteCursors.scss
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormRemoteCursors.scss
@@ -1,4 +1,4 @@
-@import "global_variables";
+@import "globalCssVariables";
.collectionFreeFormRemoteCursors-cont {
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss
index 31809f30b..392bd514f 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss
@@ -1,13 +1,13 @@
-@import "../../global_variables";
+@import "../../globalCssVariables";
.collectionfreeformview-measure {
- position: absolute;
+ position: inherit;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
.collectionfreeformview {
- position: absolute;
+ position: inherit;
top: 0;
left: 0;
width: 100%;
@@ -16,7 +16,7 @@
}
.collectionfreeformview-container {
.collectionfreeformview > .jsx-parser {
- position: absolute;
+ position: inherit;
height: 100%;
width: 100%;
}
@@ -28,8 +28,10 @@
// background-size: 30px 30px;
// }
+ border-width: $COLLECTION_BORDER_WIDTH;
box-shadow: $intermediate-color 0.2vw 0.2vw 0.8vw;
- border: 0px solid $light-color-secondary;
+ border-color: $light-color-secondary;
+ border-style: solid;
border-radius: $border-radius;
box-sizing: border-box;
position: absolute;
@@ -41,7 +43,7 @@
}
.collectionfreeformview-overlay {
.collectionfreeformview > .jsx-parser {
- position: absolute;
+ position: inherit;
height: 100%;
}
.formattedTextBox-cont {
@@ -50,10 +52,12 @@
}
opacity: 0.99;
- border: 0px solid transparent;
+ border-width: 0;
+ border-color: transparent;
+ border-style: solid;
border-radius: $border-radius;
box-sizing: border-box;
- position:absolute;
+ position: absolute;
overflow: hidden;
top: 0;
left: 0;
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 01ebbe0e1..e19dc98fa 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -1,31 +1,30 @@
-import { action, computed, observable, trace, ObservableSet, runInAction } from "mobx";
+import { action, computed, observable, runInAction } from "mobx";
import { observer } from "mobx-react";
+import Measure from "react-measure";
import { Document } from "../../../../fields/Document";
import { FieldWaiting } from "../../../../fields/Field";
import { KeyStore } from "../../../../fields/KeyStore";
+import { NumberField } from "../../../../fields/NumberField";
import { TextField } from "../../../../fields/TextField";
+import { emptyFunction, returnFalse } from "../../../../Utils";
+import { DocumentManager } from "../../../util/DocumentManager";
import { DragManager } from "../../../util/DragManager";
+import { SelectionManager } from "../../../util/SelectionManager";
import { Transform } from "../../../util/Transform";
import { undoBatch } from "../../../util/UndoManager";
+import { COLLECTION_BORDER_WIDTH } from "../../../views/globalCssVariables.scss";
import { InkingCanvas } from "../../InkingCanvas";
+import { Main } from "../../Main";
import { CollectionFreeFormDocumentView } from "../../nodes/CollectionFreeFormDocumentView";
import { DocumentContentsView } from "../../nodes/DocumentContentsView";
import { DocumentViewProps } from "../../nodes/DocumentView";
-import { COLLECTION_BORDER_WIDTH } from "../CollectionBaseView";
import { CollectionSubView } from "../CollectionSubView";
import { CollectionFreeFormLinksView } from "./CollectionFreeFormLinksView";
+import { CollectionFreeFormRemoteCursors } from "./CollectionFreeFormRemoteCursors";
import "./CollectionFreeFormView.scss";
import { MarqueeView } from "./MarqueeView";
import React = require("react");
import v5 = require("uuid/v5");
-import { CollectionFreeFormRemoteCursors } from "./CollectionFreeFormRemoteCursors";
-import { PreviewCursor } from "./PreviewCursor";
-import { DocumentManager } from "../../../util/DocumentManager";
-import { SelectionManager } from "../../../util/SelectionManager";
-import { NumberField } from "../../../../fields/NumberField";
-import { Main } from "../../Main";
-import Measure from "react-measure";
-import { returnFalse, emptyFunction } from "../../../../Utils";
@observer
export class CollectionFreeFormView extends CollectionSubView {
@@ -297,8 +296,12 @@ export class CollectionFreeFormView extends CollectionSubView {
layoutKey={KeyStore.OverlayLayout} isTopMost={this.props.isTopMost} isSelected={returnFalse} select={emptyFunction} />);
}
- getTransform = (): Transform => this.props.ScreenToLocalTransform().translate(-COLLECTION_BORDER_WIDTH, -COLLECTION_BORDER_WIDTH).translate(-this.centeringShiftX, -this.centeringShiftY).transform(this.getLocalTransform());
- getContainerTransform = (): Transform => this.props.ScreenToLocalTransform().translate(-COLLECTION_BORDER_WIDTH, -COLLECTION_BORDER_WIDTH);
+ @computed
+ get borderWidth() {
+ return this.isAnnotationOverlay ? 0 : COLLECTION_BORDER_WIDTH;
+ }
+ getTransform = (): Transform => this.props.ScreenToLocalTransform().translate(-this.borderWidth, -this.borderWidth).translate(-this.centeringShiftX, -this.centeringShiftY).transform(this.getLocalTransform());
+ getContainerTransform = (): Transform => this.props.ScreenToLocalTransform().translate(-this.borderWidth, -this.borderWidth);
getLocalTransform = (): Transform => Transform.Identity().scale(1 / this.scale).translate(this.panX, this.panY);
noScaling = () => 1;
childViews = () => this.views;
@@ -307,9 +310,9 @@ export class CollectionFreeFormView extends CollectionSubView {
const [dx, dy] = [this.centeringShiftX, this.centeringShiftY];
const panx: number = -this.props.Document.GetNumber(KeyStore.PanX, 0);
const pany: number = -this.props.Document.GetNumber(KeyStore.PanY, 0);
- const zoom: number = this.zoomScaling;
- const blay = this.backgroundView;
- const olay = this.overlayView;
+ const zoom: number = this.zoomScaling;// needs to be a variable outside of the <Measure> otherwise, reactions won't fire
+ const backgroundView = this.backgroundView; // needs to be a variable outside of the <Measure> otherwise, reactions won't fire
+ const overlayView = this.overlayView;// needs to be a variable outside of the <Measure> otherwise, reactions won't fire
return (
<Measure onResize={(r: any) => runInAction(() => { this._pwidth = r.entry.width; this._pheight = r.entry.height; })}>
@@ -317,25 +320,21 @@ export class CollectionFreeFormView extends CollectionSubView {
<div className={`collectionfreeformview-measure`} ref={measureRef}>
<div className={`collectionfreeformview${this.isAnnotationOverlay ? "-overlay" : "-container"}`}
onPointerDown={this.onPointerDown} onPointerMove={(e) => super.setCursorPosition(this.getTransform().transformPoint(e.clientX, e.clientY))}
- onDrop={this.onDrop.bind(this)} onDragOver={this.onDragOver} onWheel={this.onPointerWheel}
- style={{ borderWidth: `${COLLECTION_BORDER_WIDTH}px` }} ref={this.createDropTarget}>
+ onDrop={this.onDrop.bind(this)} onDragOver={this.onDragOver} onWheel={this.onPointerWheel} ref={this.createDropTarget}>
<MarqueeView container={this} activeDocuments={this.getActiveDocuments} selectDocuments={this.selectDocuments}
- addDocument={this.addDocument} removeDocument={this.props.removeDocument}
+ addDocument={this.addDocument} removeDocument={this.props.removeDocument} addLiveTextDocument={this.addLiveTextBox}
getContainerTransform={this.getContainerTransform} getTransform={this.getTransform}>
- <PreviewCursor container={this} addLiveTextDocument={this.addLiveTextBox}
- getContainerTransform={this.getContainerTransform} getTransform={this.getTransform} >
- <div className="collectionfreeformview" ref={this._canvasRef}
- style={{ transform: `translate(${dx}px, ${dy}px) scale(${zoom}, ${zoom}) translate(${panx}px, ${pany}px)` }}>
- {blay}
- <CollectionFreeFormLinksView {...this.props}>
- <InkingCanvas getScreenTransform={this.getTransform} Document={this.props.Document} >
- {this.childViews}
- </InkingCanvas>
- </CollectionFreeFormLinksView>
- <CollectionFreeFormRemoteCursors {...this.props} />
- </div>
- {olay}
- </PreviewCursor>
+ <div className="collectionfreeformview" ref={this._canvasRef}
+ style={{ transform: `translate(${dx}px, ${dy}px) scale(${zoom}, ${zoom}) translate(${panx}px, ${pany}px)` }}>
+ {backgroundView}
+ <CollectionFreeFormLinksView {...this.props}>
+ <InkingCanvas getScreenTransform={this.getTransform} Document={this.props.Document} >
+ {this.childViews}
+ </InkingCanvas>
+ </CollectionFreeFormLinksView>
+ <CollectionFreeFormRemoteCursors {...this.props} />
+ </div>
+ {overlayView}
</MarqueeView>
</div>
</div>)}
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.scss b/src/client/views/collections/collectionFreeForm/MarqueeView.scss
index 0b406e722..e5ffcec76 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.scss
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.scss
@@ -1,6 +1,6 @@
.marqueeView {
- position: absolute;
+ position: inherit;
top:0;
left:0;
width:100%;
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index 1e6faafb3..a4722a6f8 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -1,4 +1,4 @@
-import { action, computed, observable, trace } from "mobx";
+import { action, computed, observable } from "mobx";
import { observer } from "mobx-react";
import { Document } from "../../../../fields/Document";
import { FieldWaiting } from "../../../../fields/Field";
@@ -7,10 +7,11 @@ import { KeyStore } from "../../../../fields/KeyStore";
import { Documents } from "../../../documents/Documents";
import { SelectionManager } from "../../../util/SelectionManager";
import { Transform } from "../../../util/Transform";
+import { undoBatch } from "../../../util/UndoManager";
import { InkingCanvas } from "../../InkingCanvas";
+import { PreviewCursor } from "../../PreviewCursor";
import { CollectionFreeFormView } from "./CollectionFreeFormView";
import "./MarqueeView.scss";
-import { PreviewCursor } from "./PreviewCursor";
import React = require("react");
interface MarqueeViewProps {
@@ -21,6 +22,7 @@ interface MarqueeViewProps {
activeDocuments: () => Document[];
selectDocuments: (docs: Document[]) => void;
removeDocument: (doc: Document) => boolean;
+ addLiveTextDocument: (doc: Document) => void;
}
@observer
@@ -32,6 +34,7 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
@observable _downY: number = 0;
@observable _used: boolean = false;
@observable _visible: boolean = false;
+ _showOnUp: boolean = false;
static DRAG_THRESHOLD = 4;
@action
@@ -47,11 +50,31 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
}
@action
+ onKeyPress = (e: KeyboardEvent) => {
+ // Mixing events between React and Native is finicky. In FormattedTextBox, we set the
+ // DASHFormattedTextBoxHandled flag when a text box consumes a key press so that we can ignore
+ // the keyPress here.
+ //if not these keys, make a textbox if preview cursor is active!
+ if (!e.ctrlKey && !e.altKey && !e.defaultPrevented && !(e as any).DASHFormattedTextBoxHandled) {
+ //make textbox and add it to this collection
+ let [x, y] = this.props.getTransform().transformPoint(this._downX, this._downY);
+ let newBox = Documents.TextDocument({ width: 200, height: 100, x: x, y: y, title: "typed text" });
+ this.props.addLiveTextDocument(newBox);
+ PreviewCursor.Visible = false;
+ e.stopPropagation();
+ }
+ }
+ hideCursor = () => {
+ document.removeEventListener("keypress", this.onKeyPress, false);
+ }
+ @action
onPointerDown = (e: React.PointerEvent): void => {
if (e.buttons === 1 && !e.altKey && !e.metaKey && this.props.container.props.active()) {
this._downX = this._lastX = e.pageX;
this._downY = this._lastY = e.pageY;
this._used = false;
+ this._showOnUp = true;
+ document.removeEventListener("keypress", this.onKeyPress, false);
document.addEventListener("pointermove", this.onPointerMove, true);
document.addEventListener("pointerup", this.onPointerUp, true);
document.addEventListener("keydown", this.marqueeCommand, true);
@@ -63,6 +86,10 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
this._lastX = e.pageX;
this._lastY = e.pageY;
if (!e.cancelBubble) {
+ if (Math.abs(this._downX - e.clientX) > 4 || Math.abs(this._downY - e.clientY) > 4) {
+ this._showOnUp = false;
+ PreviewCursor.Visible = false;
+ }
if (!this._used && e.buttons === 1 && !e.altKey && !e.metaKey &&
(Math.abs(this._lastX - this._downX) > MarqueeView.DRAG_THRESHOLD || Math.abs(this._lastY - this._downY) > MarqueeView.DRAG_THRESHOLD)) {
this._visible = true;
@@ -76,11 +103,16 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
onPointerUp = (e: PointerEvent): void => {
this.cleanupInteractions(true);
this._visible = false;
- let mselect = this.marqueeSelect();
- if (!e.shiftKey) {
- SelectionManager.DeselectAll(mselect.length ? undefined : this.props.container.props.Document);
+ if (this._showOnUp) {
+ PreviewCursor.Show(this.hideCursor, this._downX, this._downY);
+ document.addEventListener("keypress", this.onKeyPress, false);
+ } else {
+ let mselect = this.marqueeSelect();
+ if (!e.shiftKey) {
+ SelectionManager.DeselectAll(mselect.length ? undefined : this.props.container.props.Document);
+ }
+ this.props.selectDocuments(mselect.length ? mselect : [this.props.container.props.Document]);
}
- this.props.selectDocuments(mselect.length ? mselect : [this.props.container.props.Document]);
}
intersectRect(r1: { left: number, top: number, width: number, height: number },
@@ -97,6 +129,7 @@ export class MarqueeView extends React.Component<MarqueeViewProps>
return { left: topLeft[0], top: topLeft[1], width: Math.abs(size[0]), height: Math.abs(size[1]) };
}
+ @undoBatch
@action
marqueeCommand = (e: KeyboardEvent) => {
if (e.key === "Backspace" || e.key === "Delete") {
diff --git a/src/client/views/collections/collectionFreeForm/PreviewCursor.scss b/src/client/views/collections/collectionFreeForm/PreviewCursor.scss
deleted file mode 100644
index 7a67c29bf..000000000
--- a/src/client/views/collections/collectionFreeForm/PreviewCursor.scss
+++ /dev/null
@@ -1,27 +0,0 @@
-
-.previewCursor {
- color: black;
- position: absolute;
- transform-origin: left top;
- top: 0;
- left:0;
- pointer-events: none;
-}
-.previewCursorView {
- top: 0;
- left:0;
- position: absolute;
- width:100%;
- height:100%;
-}
-
-//this is an animation for the blinking cursor!
-// @keyframes blink {
-// 0% {opacity: 0}
-// 49%{opacity: 0}
-// 50% {opacity: 1}
-// }
-
-// #previewCursor {
-// animation: blink 1s infinite;
-// } \ No newline at end of file
diff --git a/src/client/views/collections/collectionFreeForm/PreviewCursor.tsx b/src/client/views/collections/collectionFreeForm/PreviewCursor.tsx
deleted file mode 100644
index 8eabb020a..000000000
--- a/src/client/views/collections/collectionFreeForm/PreviewCursor.tsx
+++ /dev/null
@@ -1,120 +0,0 @@
-import { action, observable, trace, computed, reaction } from "mobx";
-import { observer } from "mobx-react";
-import { Document } from "../../../../fields/Document";
-import { Documents } from "../../../documents/Documents";
-import { Transform } from "../../../util/Transform";
-import { CollectionFreeFormView } from "./CollectionFreeFormView";
-import "./PreviewCursor.scss";
-import React = require("react");
-import { interfaceDeclaration } from "babel-types";
-
-
-export interface PreviewCursorProps {
- getTransform: () => Transform;
- getContainerTransform: () => Transform;
- container: CollectionFreeFormView;
- addLiveTextDocument: (doc: Document) => void;
-}
-
-@observer
-export class PreviewCursor extends React.Component<PreviewCursorProps> {
- @observable _lastX: number = 0;
- @observable _lastY: number = 0;
- @observable public _visible: boolean = false;
- @observable public DownX: number = 0;
- @observable public DownY: number = 0;
- _showOnUp: boolean = false;
-
- @action
- cleanupInteractions = () => {
- document.removeEventListener("pointerup", this.onPointerUp, true);
- document.removeEventListener("pointermove", this.onPointerMove, true);
- }
-
- @action
- onPointerDown = (e: React.PointerEvent) => {
- if (e.button === 0 && this.props.container.props.active()) {
- document.removeEventListener("keypress", this.onKeyPress, false);
- this._showOnUp = true;
- this.DownX = e.pageX;
- this.DownY = e.pageY;
- document.addEventListener("pointerup", this.onPointerUp, true);
- document.addEventListener("pointermove", this.onPointerMove, true);
- }
- }
- @action
- onPointerMove = (e: PointerEvent): void => {
- if (Math.abs(this.DownX - e.clientX) > 4 || Math.abs(this.DownY - e.clientY) > 4) {
- this._showOnUp = false;
- this._visible = false;
- }
- }
-
- @action
- onPointerUp = (e: PointerEvent): void => {
- if (this._showOnUp) {
- document.addEventListener("keypress", this.onKeyPress, false);
- this._lastX = this.DownX;
- this._lastY = this.DownY;
- this._visible = true;
- }
- this.cleanupInteractions();
- }
-
- @action
- onKeyPress = (e: KeyboardEvent) => {
- // Mixing events between React and Native is finicky. In FormattedTextBox, we set the
- // DASHFormattedTextBoxHandled flag when a text box consumes a key press so that we can ignore
- // the keyPress here.
- //if not these keys, make a textbox if preview cursor is active!
- if (!e.ctrlKey && !e.altKey && !e.defaultPrevented && !(e as any).DASHFormattedTextBoxHandled) {
- //make textbox and add it to this collection
- let [x, y] = this.props.getTransform().transformPoint(this._lastX, this._lastY);
- let newBox = Documents.TextDocument({ width: 200, height: 100, x: x, y: y, title: "typed text" });
- this.props.addLiveTextDocument(newBox);
- document.removeEventListener("keypress", this.onKeyPress, false);
- this._visible = false;
- e.stopPropagation();
- }
- }
-
- getPoint = () => this.props.getContainerTransform().transformPoint(this._lastX, this._lastY);
- getVisible = () => this._visible;
- setVisible = (v: boolean) => {
- this._visible = v;
- document.removeEventListener("keypress", this.onKeyPress, false);
- }
- render() {
- return (
- <div className="previewCursorView" onPointerDown={this.onPointerDown}>
- {this.props.children}
- <PreviewCursorPrompt setVisible={this.setVisible} getPoint={this.getPoint} getVisible={this.getVisible} />
- </div>
- );
- }
-}
-
-export interface PromptProps {
- getPoint: () => number[];
- getVisible: () => boolean;
- setVisible: (v: boolean) => void;
-}
-
-@observer
-export class PreviewCursorPrompt extends React.Component<PromptProps> {
- private _promptRef = React.createRef<HTMLDivElement>();
-
- //when focus is lost, this will remove the preview cursor
- @action onBlur = (): void => this.props.setVisible(false);
-
- render() {
- let p = this.props.getPoint();
- if (this.props.getVisible() && this._promptRef.current) {
- this._promptRef.current.focus();
- }
- return <div className="previewCursor" id="previewCursor" onBlur={this.onBlur} tabIndex={0} ref={this._promptRef}
- style={{ transform: `translate(${p[0]}px, ${p[1]}px)`, opacity: this.props.getVisible() ? 1 : 0 }}>
- I
- </div >;
- }
-} \ No newline at end of file