aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--package-lock.json24
-rw-r--r--package.json1
-rw-r--r--src/client/documents/DocumentTypes.ts1
-rw-r--r--src/client/documents/Documents.ts23
-rw-r--r--src/client/views/DocumentDecorations.tsx4
-rw-r--r--src/client/views/StyleProvider.tsx1
-rw-r--r--src/client/views/nodes/DocumentContentsView.tsx3
-rw-r--r--src/client/views/nodes/EquationBox.scss0
-rw-r--r--src/client/views/nodes/EquationBox.tsx66
-rw-r--r--src/client/views/nodes/formattedText/FormattedTextBox.tsx2
-rw-r--r--src/client/views/nodes/formattedText/ProsemirrorExampleTransfer.ts4
-rw-r--r--webpack.config.js6
12 files changed, 130 insertions, 5 deletions
diff --git a/package-lock.json b/package-lock.json
index 464fdfb51..933c5037c 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -5526,6 +5526,15 @@
"resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz",
"integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w=="
},
+ "equation-editor-react": {
+ "version": "0.0.6",
+ "resolved": "https://registry.npmjs.org/equation-editor-react/-/equation-editor-react-0.0.6.tgz",
+ "integrity": "sha512-7Zsx04yh4DsirpMzMVnEaDwMxrpcjiAt6NOvSj+DEOa56VfKGXsmouWFOCtSVixahDSVEDs53LbhnPqFh4cVqw==",
+ "requires": {
+ "jquery": "^3.4.1",
+ "mathquill": "^0.10.1-a"
+ }
+ },
"errno": {
"version": "0.1.7",
"resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz",
@@ -8813,6 +8822,21 @@
}
}
},
+ "mathquill": {
+ "version": "0.10.1-a",
+ "resolved": "https://registry.npmjs.org/mathquill/-/mathquill-0.10.1-a.tgz",
+ "integrity": "sha1-vyylaQEAY6w0vNXVKa3Ag3zVPD8=",
+ "requires": {
+ "jquery": "^1.12.3"
+ },
+ "dependencies": {
+ "jquery": {
+ "version": "1.12.4",
+ "resolved": "https://registry.npmjs.org/jquery/-/jquery-1.12.4.tgz",
+ "integrity": "sha1-AeHfuikP5z3rp3zurLD5ui/sngw="
+ }
+ }
+ },
"md5.js": {
"version": "1.3.5",
"resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz",
diff --git a/package.json b/package.json
index a18b11967..28d77aa38 100644
--- a/package.json
+++ b/package.json
@@ -153,6 +153,7 @@
"cookie-session": "^2.0.0-rc.1",
"cors": "^2.8.5",
"depcheck": "^0.9.2",
+ "equation-editor-react": "0.0.6",
"exif": "^0.6.0",
"express": "^4.16.4",
"express-flash": "0.0.2",
diff --git a/src/client/documents/DocumentTypes.ts b/src/client/documents/DocumentTypes.ts
index 080657fd8..20dbc6f25 100644
--- a/src/client/documents/DocumentTypes.ts
+++ b/src/client/documents/DocumentTypes.ts
@@ -21,6 +21,7 @@ export enum DocumentType {
PDFANNO = "pdfanno", // pdf text selection (could be just a collection?)
DATE = "date", // calendar view of a date
SCRIPTING = "script", // script editor
+ EQUATION = "equation", // equation edtior
// special purpose wrappers that either take no data or are compositions of lower level types
LINK = "link", // link (view of a document that acts as a link)
diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 3f03d39da..e270d2ac8 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -57,6 +57,7 @@ import { PresElementBox } from "../views/presentationview/PresElementBox";
import { SearchBox } from "../views/search/SearchBox";
import { DashWebRTCVideo } from "../views/webcam/DashWebRTCVideo";
import { DocumentType } from "./DocumentTypes";
+import { EquationBox } from "../views/nodes/EquationBox";
const path = require('path');
const defaultNativeImageDim = Number(DFLT_IMAGE_NATIVE_DIM.replace("px", ""));
@@ -241,6 +242,7 @@ export class DocumentOptions {
sidebarColor?: string; // background color of text sidebar
sidebarViewType?: string; // collection type of text sidebar
docMaxAutoHeight?: number; // maximum height for newly created (eg, from pasting) text documents
+ text?: string;
textTransform?: string; // is linear view expanded
letterSpacing?: string; // is linear view expanded
flexDirection?: "unset" | "row" | "column" | "row-reverse" | "column-reverse";
@@ -374,6 +376,9 @@ export namespace Docs {
[DocumentType.LABEL, {
layout: { view: LabelBox, dataField: defaultDataKey },
}],
+ [DocumentType.EQUATION, {
+ layout: { view: EquationBox, dataField: defaultDataKey },
+ }],
[DocumentType.BUTTON, {
layout: { view: LabelBox, dataField: "onClick" },
}],
@@ -890,6 +895,10 @@ export namespace Docs {
return InstanceFromProto(Prototypes.get(DocumentType.LABEL), undefined, { ...(options || {}) });
}
+ export function EquationDocument(options?: DocumentOptions) {
+ return InstanceFromProto(Prototypes.get(DocumentType.EQUATION), undefined, { ...(options || {}) });
+ }
+
export function ButtonDocument(options?: DocumentOptions) {
// const btn = InstanceFromProto(Prototypes.get(DocumentType.BUTTON), undefined, { ...(options || {}), "onClick-rawScript": "-script-" });
// btn.layoutKey = "layout_onClick";
@@ -1220,6 +1229,20 @@ export namespace DocUtils {
icon: "eye"
});
ContextMenu.Instance.addItem({
+ description: ":math", event: () => {
+ const created = Docs.Create.EquationDocument();
+ if (created) {
+ created.author = Doc.CurrentUserEmail;
+ created.x = x;
+ created.y = y;
+ created.width = 300;
+ created.height = 35;
+ EquationBox.SelectOnLoad = created[Id];
+ docAdder?.(created);
+ }
+ }, icon: "compress-arrows-alt"
+ });
+ ContextMenu.Instance.addItem({
description: "Add Template Doc ...",
subitems: DocListCast(Cast(Doc.UserDoc().myItemCreators, Doc, null)?.data).filter(btnDoc => !btnDoc.hidden).map(btnDoc => Cast(btnDoc?.dragFactory, Doc, null)).filter(doc => doc && doc !== Doc.UserDoc().emptyPresentation).map((dragDoc, i) => ({
description: ":" + StrCast(dragDoc.title),
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 357bff36d..5b7394c42 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -611,8 +611,8 @@ export class DocumentDecorations extends React.Component<{ boundsLeft: number, b
top: bounds.y - this._resizeBorderWidth / 2 - this._titleHeight,
}}>
{closeIcon}
- {titleArea}
- {seldoc.props.hideResizeHandles ? (null) :
+ {seldoc.props.Document.type === DocumentType.EQUATION ? (null) : titleArea}
+ {seldoc.props.hideResizeHandles || seldoc.props.Document.type === DocumentType.EQUATION ? (null) :
<>
{SelectionManager.Views().length !== 1 || seldoc.Document.type === DocumentType.INK ? (null) :
<Tooltip key="i" title={<div className="dash-tooltip">{`${seldoc.finalLayoutKey.includes("icon") ? "De" : ""}Iconify Document`}</div>} placement="top">
diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx
index 5a2fb285b..2352aa22a 100644
--- a/src/client/views/StyleProvider.tsx
+++ b/src/client/views/StyleProvider.tsx
@@ -110,6 +110,7 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<FieldViewProps |
case DocumentType.FILTER: docColor = docColor || (darkScheme() ? "#2d2d2d" : "rgba(105, 105, 105, 0.432)"); break;
case DocumentType.INK: docColor = doc?.isInkMask ? "rgba(0,0,0,0.7)" : undefined; break;
case DocumentType.SLIDER: break;
+ case DocumentType.EQUATION: docColor = docColor || "transparent"; break;
case DocumentType.LABEL: docColor = docColor || (doc.annotationOn !== undefined ? "rgba(128, 128, 128, 0.18)" : undefined); break;
case DocumentType.BUTTON: docColor = docColor || (darkScheme() ? "#2d2d2d" : "lightgray"); break;
case DocumentType.LINK: return "transparent";
diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx
index c0af1e08a..02c112745 100644
--- a/src/client/views/nodes/DocumentContentsView.tsx
+++ b/src/client/views/nodes/DocumentContentsView.tsx
@@ -11,6 +11,7 @@ import { CollectionView } from "../collections/CollectionView";
import { YoutubeBox } from "./../../apis/youtube/YoutubeBox";
import { AudioBox } from "./AudioBox";
import { LabelBox } from "./LabelBox";
+import { EquationBox } from "./EquationBox";
import { SliderBox } from "./SliderBox";
import { LinkBox } from "./LinkBox";
import { ScriptingBox } from "./ScriptingBox";
@@ -220,7 +221,7 @@ export class DocumentContentsView extends React.Component<DocumentViewProps & Fo
blacklistedAttrs={emptyPath}
renderInWrapper={false}
components={{
- FormattedTextBox, ImageBox, DirectoryImportBox, FontIconBox, LabelBox, SliderBox, FieldView,
+ FormattedTextBox, ImageBox, DirectoryImportBox, FontIconBox, LabelBox, EquationBox, SliderBox, FieldView,
CollectionFreeFormView, CollectionDockingView, CollectionSchemaView, CollectionView, WebBox, KeyValueBox,
PDFBox, VideoBox, AudioBox, PresBox, YoutubeBox, PresElementBox, SearchBox, FilterBox,
ColorBox, DashWebRTCVideo, LinkAnchorBox, InkingStroke, DocHolderBox, LinkBox, ScriptingBox,
diff --git a/src/client/views/nodes/EquationBox.scss b/src/client/views/nodes/EquationBox.scss
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/src/client/views/nodes/EquationBox.scss
diff --git a/src/client/views/nodes/EquationBox.tsx b/src/client/views/nodes/EquationBox.tsx
new file mode 100644
index 000000000..8ded4111c
--- /dev/null
+++ b/src/client/views/nodes/EquationBox.tsx
@@ -0,0 +1,66 @@
+import EquationEditor from 'equation-editor-react';
+import { observer } from 'mobx-react';
+import * as React from 'react';
+import { documentSchema } from '../../../fields/documentSchemas';
+import { createSchema, makeInterface } from '../../../fields/Schema';
+import { StrCast, NumCast } from '../../../fields/Types';
+import { ViewBoxBaseComponent } from '../DocComponent';
+import { FieldView, FieldViewProps } from './FieldView';
+import './LabelBox.scss';
+import { Id } from '../../../fields/FieldSymbols';
+import { simulateMouseClick } from '../../../Utils';
+import { TraceMobx } from '../../../fields/util';
+import { reaction, action } from 'mobx';
+import { Docs } from '../../documents/Documents';
+
+const EquationSchema = createSchema({});
+
+type EquationDocument = makeInterface<[typeof EquationSchema, typeof documentSchema]>;
+const EquationDocument = makeInterface(EquationSchema, documentSchema);
+
+@observer
+export class EquationBox extends ViewBoxBaseComponent<FieldViewProps, EquationDocument>(EquationDocument) {
+ public static LayoutString(fieldKey: string) { return FieldView.LayoutString(EquationBox, fieldKey); }
+ public static SelectOnLoad: string = "";
+ _ref: React.RefObject<EquationEditor> = React.createRef();
+ componentDidMount() {
+ if (EquationBox.SelectOnLoad === this.rootDoc[Id]) {
+ this.props.select(false);
+
+ this._ref.current!.mathField.focus();
+ this._ref.current!.mathField.select();
+ }
+ reaction(() => this.props.isSelected(),
+ selected => {
+ if (this._ref.current) {
+ if (selected) this._ref.current.element.current.children[0].addEventListener("keydown", this.keyPressed, true);
+ else this._ref.current.element.current.children[0].removeEventListener("keydown", this.keyPressed);
+ }
+ }, { fireImmediately: true });
+ }
+ @action
+ keyPressed = (e: KeyboardEvent) => {
+ if (e.key === "Enter") {
+ const _height = Number(getComputedStyle(this._ref.current!.element.current).height.replace("px", ""));
+ const _width = Number(getComputedStyle(this._ref.current!.element.current).width.replace("px", ""));
+ this.layoutDoc._width = _width;
+ this.layoutDoc._height = _height;
+ const nextEq = Docs.Create.EquationDocument({ title: "# math", text: StrCast(this.dataDoc.text), x: NumCast(this.layoutDoc.x), y: NumCast(this.layoutDoc.y) + _height + 10, _width, _height: 35 });
+ EquationBox.SelectOnLoad = nextEq[Id];
+ this.props.addDocument?.(nextEq);
+ e.stopPropagation();
+ }
+ if (e.key === "Backspace" && !this.dataDoc.text) this.props.removeDocument?.(this.rootDoc);
+ }
+ onChange = (str: string) => this.dataDoc.text = str;
+ render() {
+ TraceMobx();
+ return (<div onPointerDown={e => this.props.isSelected() && !e.ctrlKey && e.stopPropagation()}>
+ <EquationEditor ref={this._ref}
+ value={this.dataDoc.text || "y"}
+ onChange={this.onChange}
+ autoCommands="pi theta sqrt sum prod alpha beta gamma rho"
+ autoOperatorNames="sin cos tan" /></div>
+ );
+ }
+} \ No newline at end of file
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index 288cd14c9..5066578aa 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -1541,7 +1541,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp
/>
</div>
{this.props.noSidebar || !this.layoutDoc._showSidebar || this.sidebarWidthPercent === "0%" ? (null) : this.sidebarCollection}
- {this.sidebarHandle}
+ {this.Document._singleLine ? (null) : this.sidebarHandle}
{!this.layoutDoc._showAudio ? (null) : this.audioHandle}
</div>
</div>
diff --git a/src/client/views/nodes/formattedText/ProsemirrorExampleTransfer.ts b/src/client/views/nodes/formattedText/ProsemirrorExampleTransfer.ts
index a1a404e10..eae4c0179 100644
--- a/src/client/views/nodes/formattedText/ProsemirrorExampleTransfer.ts
+++ b/src/client/views/nodes/formattedText/ProsemirrorExampleTransfer.ts
@@ -144,6 +144,10 @@ export function buildKeymap<S extends Schema<any>>(schema: S, props: any, mapKey
bind("Alt-\\", setBlockType(schema.nodes.paragraph));
bind("Shift-Ctrl-\\", setBlockType(schema.nodes.code_block));
+ bind("Ctrl-m", (state: EditorState<S>, dispatch: (tx: Transaction<S>) => void) => {
+ dispatch(state.tr.replaceSelectionWith(schema.nodes.dashField.create({ fieldKey: "math" + Utils.GenerateGuid() })));
+ })
+
for (let i = 1; i <= 6; i++) {
bind("Shift-Ctrl-" + i, setBlockType(schema.nodes.heading, { level: i }));
}
diff --git a/webpack.config.js b/webpack.config.js
index c973be1ed..30967d618 100644
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -75,6 +75,10 @@ module.exports = {
}]
},
{
+ test: /\.(woff|woff2|ttf|eot|otf|svg)$/,
+ use: 'file-loader?name=fonts/[name].[ext]!static'
+ },
+ {
test: /\.scss|css$/,
use: [{
loader: "style-loader"
@@ -84,7 +88,7 @@ module.exports = {
},
{
loader: "sass-loader"
- }
+ },
]
},
{