aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--package-lock.json225
-rw-r--r--package.json1
-rw-r--r--src/client/documents/DocumentTypes.ts3
-rw-r--r--src/client/documents/Documents.ts10
-rw-r--r--src/client/util/CurrentUserUtils.ts2
-rw-r--r--src/client/views/collections/CollectionStackingView.tsx39
-rw-r--r--src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx2
-rw-r--r--src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx2
-rw-r--r--src/client/views/nodes/DocumentContentsView.tsx3
-rw-r--r--src/client/views/nodes/DocumentView.tsx17
-rw-r--r--src/client/views/nodes/EquationBox.tsx39
-rw-r--r--src/client/views/nodes/FunctionPlotBox.scss0
-rw-r--r--src/client/views/nodes/FunctionPlotBox.tsx76
13 files changed, 373 insertions, 46 deletions
diff --git a/package-lock.json b/package-lock.json
index 47aa1f0ea..3cbdb7a74 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -550,6 +550,11 @@
"@types/glob": "*"
}
},
+ "@types/assert": {
+ "version": "1.5.4",
+ "resolved": "https://registry.npmjs.org/@types/assert/-/assert-1.5.4.tgz",
+ "integrity": "sha512-CaFVW21Ulu0J9sUaEWJjwmhkDkeoxa4fniVSERzZC13sU9v8NNM2lMlkfZZv60j47D+qDt0Lyo8skVP3CTXUdA=="
+ },
"@types/async": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/@types/async/-/async-2.4.2.tgz",
@@ -2862,6 +2867,14 @@
"integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=",
"dev": true
},
+ "built-in-math-eval": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/built-in-math-eval/-/built-in-math-eval-0.3.0.tgz",
+ "integrity": "sha1-JA3CHLOJQ5WIxhxGDrAHZJfvxBw=",
+ "requires": {
+ "math-codegen": "^0.3.5"
+ }
+ },
"builtin-modules": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz",
@@ -3685,6 +3698,11 @@
"safe-buffer": "^5.0.1"
}
},
+ "clamp": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/clamp/-/clamp-1.0.1.tgz",
+ "integrity": "sha1-ZqDmQBGBbjcZaCj9yMjBRzEshjQ="
+ },
"class-transformer": {
"version": "0.2.3",
"resolved": "https://registry.npmjs.org/class-transformer/-/class-transformer-0.2.3.tgz",
@@ -4639,6 +4657,130 @@
"resolved": "https://registry.npmjs.org/d3-array/-/d3-array-1.2.4.tgz",
"integrity": "sha512-KHW6M86R+FUPYGb3R5XiYjXPq7VzwxZ22buHhAEVG5ztoEcZZMLov530mmccaqA1GghZArjQV46fuc8kUqhhHw=="
},
+ "d3-axis": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/d3-axis/-/d3-axis-2.0.0.tgz",
+ "integrity": "sha512-9nzB0uePtb+u9+dWir+HTuEAKJOEUYJoEwbJPsZ1B4K3iZUgzJcSENQ05Nj7S4CIfbZZ8/jQGoUzGKFznBhiiQ=="
+ },
+ "d3-color": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-2.0.0.tgz",
+ "integrity": "sha512-SPXi0TSKPD4g9tw0NMZFnR95XVgUZiBH+uUTqQuDu1OsE2zomHU7ho0FISciaPvosimixwHFl3WHLGabv6dDgQ=="
+ },
+ "d3-dispatch": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-2.0.0.tgz",
+ "integrity": "sha512-S/m2VsXI7gAti2pBoLClFFTMOO1HTtT0j99AuXLoGFKO6deHDdnv6ZGTxSTTUTgO1zVcv82fCOtDjYK4EECmWA=="
+ },
+ "d3-drag": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-2.0.0.tgz",
+ "integrity": "sha512-g9y9WbMnF5uqB9qKqwIIa/921RYWzlUDv9Jl1/yONQwxbOfszAWTCm8u7HOTgJgRDXiRZN56cHT9pd24dmXs8w==",
+ "requires": {
+ "d3-dispatch": "1 - 2",
+ "d3-selection": "2"
+ }
+ },
+ "d3-ease": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-2.0.0.tgz",
+ "integrity": "sha512-68/n9JWarxXkOWMshcT5IcjbB+agblQUaIsbnXmrzejn2O82n3p2A9R2zEB9HIEFWKFwPAEDDN8gR0VdSAyyAQ=="
+ },
+ "d3-format": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-2.0.0.tgz",
+ "integrity": "sha512-Ab3S6XuE/Q+flY96HXT0jOXcM4EAClYFnRGY5zsjRGNy6qCYrQsMffs7cV5Q9xejb35zxW5hf/guKw34kvIKsA=="
+ },
+ "d3-interpolate": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-2.0.1.tgz",
+ "integrity": "sha512-c5UhwwTs/yybcmTpAVqwSFl6vrQ8JZJoT5F7xNFK9pymv5C0Ymcc9/LIJHtYIggg/yS9YHw8i8O8tgb9pupjeQ==",
+ "requires": {
+ "d3-color": "1 - 2"
+ }
+ },
+ "d3-path": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-2.0.0.tgz",
+ "integrity": "sha512-ZwZQxKhBnv9yHaiWd6ZU4x5BtCQ7pXszEV9CU6kRgwIQVQGLMv1oiL4M+MK/n79sYzsj+gcgpPQSctJUsLN7fA=="
+ },
+ "d3-scale": {
+ "version": "3.2.3",
+ "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-3.2.3.tgz",
+ "integrity": "sha512-8E37oWEmEzj57bHcnjPVOBS3n4jqakOeuv1EDdQSiSrYnMCBdMd3nc4HtKk7uia8DUHcY/CGuJ42xxgtEYrX0g==",
+ "requires": {
+ "d3-array": "^2.3.0",
+ "d3-format": "1 - 2",
+ "d3-interpolate": "1.2.0 - 2",
+ "d3-time": "1 - 2",
+ "d3-time-format": "2 - 3"
+ },
+ "dependencies": {
+ "d3-array": {
+ "version": "2.11.0",
+ "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-2.11.0.tgz",
+ "integrity": "sha512-26clcwmHQEdsLv34oNKq5Ia9tQ26Y/4HqS3dQzF42QBUqymZJ+9PORcN1G52bt37NsL2ABoX4lvyYZc+A9Y0zw==",
+ "requires": {
+ "internmap": "^1.0.0"
+ }
+ }
+ }
+ },
+ "d3-selection": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-2.0.0.tgz",
+ "integrity": "sha512-XoGGqhLUN/W14NmaqcO/bb1nqjDAw5WtSYb2X8wiuQWvSZUsUVYsOSkOybUrNvcBjaywBdYPy03eXHMXjk9nZA=="
+ },
+ "d3-shape": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-2.0.0.tgz",
+ "integrity": "sha512-djpGlA779ua+rImicYyyjnOjeubyhql1Jyn1HK0bTyawuH76UQRWXd+pftr67H6Fa8hSwetkgb/0id3agKWykw==",
+ "requires": {
+ "d3-path": "1 - 2"
+ }
+ },
+ "d3-time": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-2.0.0.tgz",
+ "integrity": "sha512-2mvhstTFcMvwStWd9Tj3e6CEqtOivtD8AUiHT8ido/xmzrI9ijrUUihZ6nHuf/vsScRBonagOdj0Vv+SEL5G3Q=="
+ },
+ "d3-time-format": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-3.0.0.tgz",
+ "integrity": "sha512-UXJh6EKsHBTjopVqZBhFysQcoXSv/5yLONZvkQ5Kk3qbwiUYkdX17Xa1PT6U1ZWXGGfB1ey5L8dKMlFq2DO0Ag==",
+ "requires": {
+ "d3-time": "1 - 2"
+ }
+ },
+ "d3-timer": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-2.0.0.tgz",
+ "integrity": "sha512-TO4VLh0/420Y/9dO3+f9abDEFYeCUr2WZRlxJvbp4HPTQcSylXNiL6yZa9FIUvV1yRiFufl1bszTCLDqv9PWNA=="
+ },
+ "d3-transition": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-2.0.0.tgz",
+ "integrity": "sha512-42ltAGgJesfQE3u9LuuBHNbGrI/AJjNL2OAUdclE70UE6Vy239GCBEYD38uBPoLeNsOhFStGpPI0BAOV+HMxog==",
+ "requires": {
+ "d3-color": "1 - 2",
+ "d3-dispatch": "1 - 2",
+ "d3-ease": "1 - 2",
+ "d3-interpolate": "1 - 2",
+ "d3-timer": "1 - 2"
+ }
+ },
+ "d3-zoom": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-2.0.0.tgz",
+ "integrity": "sha512-fFg7aoaEm9/jf+qfstak0IYpnesZLiMX6GZvXtUSdv8RH2o4E2qeelgdU09eKS6wGuiGMfcnMI0nTIqWzRHGpw==",
+ "requires": {
+ "d3-dispatch": "1 - 2",
+ "d3-drag": "2",
+ "d3-interpolate": "1 - 2",
+ "d3-selection": "2",
+ "d3-transition": "2"
+ }
+ },
"dashdash": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
@@ -5309,6 +5451,11 @@
"integrity": "sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw==",
"dev": true
},
+ "double-bits": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/double-bits/-/double-bits-1.1.1.tgz",
+ "integrity": "sha1-WKu6RUlNpND6Nrc60RoobJGEscY="
+ },
"duplexer3": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz",
@@ -6574,6 +6721,24 @@
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
},
+ "function-plot": {
+ "version": "1.22.7",
+ "resolved": "https://registry.npmjs.org/function-plot/-/function-plot-1.22.7.tgz",
+ "integrity": "sha512-rB6FeVqvgNECmt5PhIvFFEOyEjM9AWLIpMkj9Nzbzq9f81Irgn3ZrXAuv5+qnuzM99jPL7ZM4kK3+ImiKXcSHA==",
+ "requires": {
+ "built-in-math-eval": "^0.3.0",
+ "clamp": "^1.0.1",
+ "d3-axis": "^2.0.0",
+ "d3-color": "^2.0.0",
+ "d3-format": "^2.0.0",
+ "d3-interpolate": "^2.0.1",
+ "d3-scale": "^3.2.2",
+ "d3-selection": "^2.0.0",
+ "d3-shape": "^2.0.0",
+ "d3-zoom": "^2.0.0",
+ "interval-arithmetic-eval": "^0.4.7"
+ }
+ },
"gauge": {
"version": "2.7.4",
"resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz",
@@ -7652,11 +7817,36 @@
"ipaddr.js": "^1.9.0"
}
},
+ "internmap": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/internmap/-/internmap-1.0.0.tgz",
+ "integrity": "sha512-SdoDWwNOTE2n4JWUsLn4KXZGuZPjPF9yyOGc8bnfWnBQh7BD/l80rzSznKc/r4Y0aQ7z3RTk9X+tV4tHBpu+dA=="
+ },
"interpret": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/interpret/-/interpret-1.2.0.tgz",
"integrity": "sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw=="
},
+ "interval-arithmetic": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/interval-arithmetic/-/interval-arithmetic-1.0.6.tgz",
+ "integrity": "sha512-eVotDGYPNiEaJ63oa4CeEHgOczZJ3gNHqG5wfVQ2o8sN2CEczQyR82Sjey/Bp36x8e7PtBcBvitcMnw6VUpjgQ==",
+ "requires": {
+ "@types/assert": "^1.4.6",
+ "is-safe-integer": "^2.0.0",
+ "nextafter": "^1.0.0",
+ "typedarray": "0.0.6"
+ }
+ },
+ "interval-arithmetic-eval": {
+ "version": "0.4.7",
+ "resolved": "https://registry.npmjs.org/interval-arithmetic-eval/-/interval-arithmetic-eval-0.4.7.tgz",
+ "integrity": "sha512-ClK+N4efbsgjlZR8h0qd0LQbyzUzJ9IkrjmTnD5MVb4Ytebd0lesoVP4AxLclcsEI+nIieskQ8cepHIWUPaRhQ==",
+ "requires": {
+ "interval-arithmetic": "^1.0.6",
+ "math-codegen": "^0.3.5"
+ }
+ },
"ip": {
"version": "1.1.5",
"resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz",
@@ -7948,6 +8138,14 @@
"resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.2.0.tgz",
"integrity": "sha512-RUbUeKwvm3XG2VYamhJL1xFktgjvPzL0Hq8C+6yrWIswDy3BIXGqCxhxkc30N9jqK311gVU137K8Ei55/zVJRg=="
},
+ "is-safe-integer": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-safe-integer/-/is-safe-integer-2.0.0.tgz",
+ "integrity": "sha512-eDaA39/1+3SNtYTRP28lRYOHMwiB1gfqXQaXcf/+f4mLwKgm8TTDkwJldsdtbgrK1R5CoDbf6AQ0KqP7BKoGtQ==",
+ "requires": {
+ "max-safe-integer": "^1.0.0"
+ }
+ },
"is-stream": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
@@ -8822,6 +9020,15 @@
}
}
},
+ "math-codegen": {
+ "version": "0.3.5",
+ "resolved": "https://registry.npmjs.org/math-codegen/-/math-codegen-0.3.5.tgz",
+ "integrity": "sha1-R5nuRnfe0Ud2bQA8ykt4ee3UDMo=",
+ "requires": {
+ "extend": "^3.0.0",
+ "mr-parser": "^0.2.1"
+ }
+ },
"mathquill": {
"version": "0.10.1-a",
"resolved": "https://registry.npmjs.org/mathquill/-/mathquill-0.10.1-a.tgz",
@@ -8837,6 +9044,11 @@
}
}
},
+ "max-safe-integer": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/max-safe-integer/-/max-safe-integer-1.0.1.tgz",
+ "integrity": "sha1-84BgvixWPYwC5tSK85Ei/YO29BA="
+ },
"md5.js": {
"version": "1.3.5",
"resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz",
@@ -9343,6 +9555,11 @@
}
}
},
+ "mr-parser": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/mr-parser/-/mr-parser-0.2.1.tgz",
+ "integrity": "sha1-hhi5ukF+KOn0OaQcaVtVTq/u2Sc="
+ },
"ms": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
@@ -9428,6 +9645,14 @@
"resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz",
"integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw="
},
+ "nextafter": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/nextafter/-/nextafter-1.0.0.tgz",
+ "integrity": "sha1-t9d7U1MQ4+CX5gJauwqQNHfsGjo=",
+ "requires": {
+ "double-bits": "^1.1.0"
+ }
+ },
"nice-try": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz",
diff --git a/package.json b/package.json
index 1f27b1ae6..aae4fdfff 100644
--- a/package.json
+++ b/package.json
@@ -165,6 +165,7 @@
"fit-curve": "^0.1.7",
"flexlayout-react": "^0.3.11",
"formidable": "^1.2.1",
+ "function-plot": "^1.22.7",
"golden-layout": "^1.5.9",
"google-auth-library": "^4.2.4",
"google-maps-react": "^2.0.6",
diff --git a/src/client/documents/DocumentTypes.ts b/src/client/documents/DocumentTypes.ts
index 20dbc6f25..58b120e7d 100644
--- a/src/client/documents/DocumentTypes.ts
+++ b/src/client/documents/DocumentTypes.ts
@@ -21,7 +21,8 @@ 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
+ EQUATION = "equation", // equation editor
+ FUNCPLOT = "funcplot", // function plotter
// 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 f87c7185c..ca5ee9cbd 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -58,6 +58,7 @@ import { SearchBox } from "../views/search/SearchBox";
import { DashWebRTCVideo } from "../views/webcam/DashWebRTCVideo";
import { DocumentType } from "./DocumentTypes";
import { EquationBox } from "../views/nodes/EquationBox";
+import { FunctionPlotBox } from "../views/nodes/FunctionPlotBox";
const path = require('path');
const defaultNativeImageDim = Number(DFLT_IMAGE_NATIVE_DIM.replace("px", ""));
@@ -379,6 +380,9 @@ export namespace Docs {
[DocumentType.EQUATION, {
layout: { view: EquationBox, dataField: defaultDataKey },
}],
+ [DocumentType.FUNCPLOT, {
+ layout: { view: FunctionPlotBox, dataField: defaultDataKey },
+ }],
[DocumentType.BUTTON, {
layout: { view: LabelBox, dataField: "onClick" },
}],
@@ -899,6 +903,10 @@ export namespace Docs {
return InstanceFromProto(Prototypes.get(DocumentType.EQUATION), undefined, { ...(options || {}) });
}
+ export function FunctionPlotDocument(documents: Array<Doc>, options?: DocumentOptions) {
+ return InstanceFromProto(Prototypes.get(DocumentType.FUNCPLOT), new List(documents), { ...(options || {}) });
+ }
+
export function ButtonDocument(options?: DocumentOptions) {
// const btn = InstanceFromProto(Prototypes.get(DocumentType.BUTTON), undefined, { ...(options || {}), "onClick-rawScript": "-script-" });
// btn.layoutKey = "layout_onClick";
@@ -1229,7 +1237,7 @@ export namespace DocUtils {
icon: "eye"
});
ContextMenu.Instance.addItem({
- description: ":math", event: () => {
+ description: ":=math", event: () => {
const created = Docs.Create.EquationDocument();
if (created) {
created.author = Doc.CurrentUserEmail;
diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index 79a493dc9..a2f59e48f 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -793,7 +793,7 @@ export class CurrentUserUtils {
// setup Recently Closed library item
if (doc.myRecentlyClosedDocs === undefined) {
doc.myRecentlyClosedDocs = new PrefetchProxy(Docs.Create.TreeDocument([], {
- title: "Recently Closed", _height: 500,
+ title: "Recently Closed",
treeViewHideTitle: true, _xMargin: 5, _yMargin: 5, _gridGap: 5, _forceActive: true, childDropAction: "alias",
treeViewTruncateTitleWidth: 150, treeViewPreventOpen: false, ignoreClick: true,
_lockedPosition: true, boxShadow: "0 0", dontRegisterChildViews: true, targetDropAction: "same", system: true
diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx
index 7152f4272..95a95b10d 100644
--- a/src/client/views/collections/CollectionStackingView.tsx
+++ b/src/client/views/collections/CollectionStackingView.tsx
@@ -30,6 +30,7 @@ import { CollectionStackingViewFieldColumn } from "./CollectionStackingViewField
import { CollectionSubView } from "./CollectionSubView";
import { CollectionViewType } from "./CollectionView";
import { LightboxView } from "../LightboxView";
+import { DocumentType } from "../../documents/DocumentTypes";
const _global = (window /* browser */ || global /* node */) as any;
type StackingDocument = makeInterface<[typeof collectionSchema, typeof documentSchema]>;
@@ -220,8 +221,8 @@ export class CollectionStackingView extends CollectionSubView<StackingDocument,
LayoutTemplate={this.props.childLayoutTemplate}
LayoutTemplateString={this.props.childLayoutString}
freezeDimensions={this.props.childFreezeDimensions}
- NativeWidth={this.props.childIgnoreNativeSize ? returnZero : undefined} // explicitly ignore nativeWidth/height if childIgnoreNativeSize is set- used by PresBox
- NativeHeight={this.props.childIgnoreNativeSize ? returnZero : undefined}
+ NativeWidth={this.props.childIgnoreNativeSize ? returnZero : doc._fitWidth && !Doc.NativeWidth(doc) ? width : undefined} // explicitly ignore nativeWidth/height if childIgnoreNativeSize is set- used by PresBox
+ NativeHeight={this.props.childIgnoreNativeSize ? returnZero : doc._fitWidth && !Doc.NativeHeight(doc) ? height : undefined}
dontCenter={this.props.childIgnoreNativeSize ? "xy" : undefined}
dontRegisterView={dataDoc ? true : BoolCast(this.layoutDoc.dontRegisterChildViews, this.props.dontRegisterView)}
rootSelected={this.rootSelected}
@@ -257,27 +258,29 @@ export class CollectionStackingView extends CollectionSubView<StackingDocument,
getDocWidth(d?: Doc) {
if (!d) return 0;
const childLayoutDoc = Doc.Layout(d, this.props.childLayoutTemplate?.());
- const nw = Doc.NativeWidth(childLayoutDoc) || (childLayoutDoc._fitWidth ? 0 : d[WidthSym]());
- return Math.min(nw && !this.layoutDoc._columnsFill ? (this.props.scaling?.() || 1) * d[WidthSym]() : Number.MAX_VALUE, this.columnWidth / this.numGroupColumns);
+ const maxWidth = this.columnWidth / this.numGroupColumns;
+ if (!this.layoutDoc._columnsFill && !childLayoutDoc._fitWidth) {
+ return Math.min(d[WidthSym]() * (this.props.scaling?.() || 1), maxWidth);
+ }
+ return maxWidth;
}
getDocHeight(d?: Doc) {
if (!d) return 0;
- const childDataDoc = (!d.isTemplateDoc && !d.isTemplateForField && !d.PARAMS) ? undefined : this.props.DataDoc;
const childLayoutDoc = Doc.Layout(d, this.props.childLayoutTemplate?.());
- const nw = Doc.NativeWidth(childLayoutDoc, childDataDoc) || (childLayoutDoc._fitWidth ? 0 : d[WidthSym]());
- const nh = Doc.NativeHeight(childLayoutDoc, childDataDoc) || (childLayoutDoc._fitWidth ? 0 : d[HeightSym]());
- let wid = this.columnWidth / (this.isStackingView ? this.numGroupColumns : 1);
- if (!this.layoutDoc._columnsFill) wid = Math.min(wid, childLayoutDoc[WidthSym]());
- const hllimit = NumCast(this.layoutDoc.childLimitHeight, -1);
- if (!childLayoutDoc._fitWidth && nw && nh) {
- const aspect = nw && nh ? nh / nw : 1;
- if (!(this.layoutDoc._columnsFill)) wid = Math.min(this.getDocWidth(d), wid);
- return Math.min(hllimit === 0 ? this.props.PanelWidth() : hllimit === -1 ? 10000 : hllimit, wid * aspect);
+ const childDataDoc = (!d.isTemplateDoc && !d.isTemplateForField && !d.PARAMS) ? undefined : this.props.DataDoc;
+ const maxHeight = (lim => lim === 0 ? this.props.PanelWidth() : lim === -1 ? 10000 : lim)(NumCast(this.layoutDoc.childLimitHeight, -1));
+ const nw = Doc.NativeWidth(childLayoutDoc, childDataDoc) || (!childLayoutDoc._fitWidth || this.layoutDoc._columnsFill ? d[WidthSym]() : 0);
+ const nh = Doc.NativeHeight(childLayoutDoc, childDataDoc) || (!childLayoutDoc._fitWidth || this.layoutDoc._columnsFill ? d[HeightSym]() : 0);
+ if (nw && nh) {
+ const colWid = this.columnWidth / (this.isStackingView ? this.numGroupColumns : 1);
+ const docWid = this.layoutDoc._columnsFill ? colWid : Math.min(this.getDocWidth(d), colWid);
+ return Math.min(
+ maxHeight,
+ docWid * nh / nw);
}
- return childLayoutDoc._fitWidth ?
- (!nh ? Math.min(NumCast(childLayoutDoc.height, 10000) * (this.props.scaling?.() || 1), this.props.PanelHeight() - 2 * this.yMargin) :
- Math.min(wid * nh / (nw || 1), this.layoutDoc._autoHeight ? 100000 : this.props.PanelHeight() - 2 * this.yMargin)) :
- Math.min(hllimit === 0 ? this.props.PanelWidth() : hllimit === -1 ? 10000 : hllimit, Math.max(20, childLayoutDoc[HeightSym]()));
+ const childHeight = NumCast(childLayoutDoc._height);
+ const panelHeight = this.props.PanelHeight() - 2 * this.yMargin;
+ return Math.min(childHeight, maxHeight, panelHeight);
}
columnDividerDown = (e: React.PointerEvent) => {
diff --git a/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx b/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx
index d23f3309e..0c0dbef9f 100644
--- a/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx
+++ b/src/client/views/collections/collectionMulticolumn/CollectionMulticolumnView.tsx
@@ -182,7 +182,7 @@ export class CollectionMulticolumnView extends CollectionSubView(MulticolumnDocu
let offset = 0;
for (const { layout: candidate } of this.childLayoutPairs) {
if (candidate === layout) {
- return this.props.ScreenToLocalTransform().translate(-offset, 0);
+ return this.props.ScreenToLocalTransform().translate(-offset / (this.props.scaling?.() || 1), 0);
}
offset += this.lookupPixels(candidate) + resizerWidth;
}
diff --git a/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx b/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx
index 641ae6ce1..0a1000a20 100644
--- a/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx
+++ b/src/client/views/collections/collectionMulticolumn/CollectionMultirowView.tsx
@@ -182,7 +182,7 @@ export class CollectionMultirowView extends CollectionSubView(MultirowDocument)
let offset = 0;
for (const { layout: candidate } of this.childLayoutPairs) {
if (candidate === layout) {
- return this.props.ScreenToLocalTransform().translate(0, -offset);
+ return this.props.ScreenToLocalTransform().translate(0, -offset / (this.props.scaling?.() || 1));
}
offset += this.lookupPixels(candidate) + resizerHeight;
}
diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx
index 02c112745..32542d056 100644
--- a/src/client/views/nodes/DocumentContentsView.tsx
+++ b/src/client/views/nodes/DocumentContentsView.tsx
@@ -12,6 +12,7 @@ import { YoutubeBox } from "./../../apis/youtube/YoutubeBox";
import { AudioBox } from "./AudioBox";
import { LabelBox } from "./LabelBox";
import { EquationBox } from "./EquationBox";
+import { FunctionPlotBox } from "./FunctionPlotBox";
import { SliderBox } from "./SliderBox";
import { LinkBox } from "./LinkBox";
import { ScriptingBox } from "./ScriptingBox";
@@ -223,7 +224,7 @@ export class DocumentContentsView extends React.Component<DocumentViewProps & Fo
components={{
FormattedTextBox, ImageBox, DirectoryImportBox, FontIconBox, LabelBox, EquationBox, SliderBox, FieldView,
CollectionFreeFormView, CollectionDockingView, CollectionSchemaView, CollectionView, WebBox, KeyValueBox,
- PDFBox, VideoBox, AudioBox, PresBox, YoutubeBox, PresElementBox, SearchBox, FilterBox,
+ PDFBox, VideoBox, AudioBox, PresBox, YoutubeBox, PresElementBox, SearchBox, FilterBox, FunctionPlotBox,
ColorBox, DashWebRTCVideo, LinkAnchorBox, InkingStroke, DocHolderBox, LinkBox, ScriptingBox,
ScreenshotBox, HTMLtag, ComparisonBox
}}
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index cd61d20b1..d4f6c076a 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -1013,25 +1013,22 @@ export class DocumentView extends React.Component<DocumentViewProps> {
return this.docView?._componentView?.reverseNativeScaling?.() ? 0 :
returnVal(this.props.NativeHeight?.(), Doc.NativeHeight(this.layoutDoc, this.props.DataDoc, this.props.freezeDimensions));
}
- shouldNotScale = () => this.layoutDoc._fitWidth || [CollectionViewType.Docking, CollectionViewType.Tree].includes(this.Document._viewType as any);
- @computed get effectiveNativeWidth() { return this.nativeWidth || (this.shouldNotScale() ? 0 : NumCast(this.layoutDoc.width)); }
- @computed get effectiveNativeHeight() { return this.nativeHeight || (this.shouldNotScale() ? 0 : NumCast(this.layoutDoc.height)); }
+ shouldNotScale = () => (this.layoutDoc._fitWidth && !this.nativeWidth) || [CollectionViewType.Docking, CollectionViewType.Tree].includes(this.Document._viewType as any);
+ @computed get effectiveNativeWidth() { return this.shouldNotScale() ? 0 : (this.nativeWidth || NumCast(this.layoutDoc.width)); }
+ @computed get effectiveNativeHeight() { return this.shouldNotScale() ? 0 : (this.nativeHeight || NumCast(this.layoutDoc.height)); }
@computed get nativeScaling() {
+ if (this.shouldNotScale()) return 1;
const minTextScale = this.Document.type === DocumentType.RTF ? 0.1 : 0;
- if (this.effectiveNativeWidth && (this.layoutDoc?._fitWidth || this.props.PanelHeight() / this.effectiveNativeHeight > this.props.PanelWidth() / this.effectiveNativeWidth)) {
+ if (this.props.PanelHeight() / this.effectiveNativeHeight > this.props.PanelWidth() / this.effectiveNativeWidth) {
return Math.max(minTextScale, this.props.PanelWidth() / this.effectiveNativeWidth); // width-limited or fitWidth
}
- return this.effectiveNativeWidth && this.effectiveNativeHeight ? Math.max(minTextScale, this.props.PanelHeight() / this.effectiveNativeHeight) : 1; // height-limited or unscaled
+ return Math.max(minTextScale, this.props.PanelHeight() / this.effectiveNativeHeight); // height-limited or unscaled
}
@computed get panelWidth() { return this.effectiveNativeWidth ? this.effectiveNativeWidth * this.nativeScaling : this.props.PanelWidth(); }
@computed get panelHeight() {
if (this.effectiveNativeHeight) {
- return Math.min(this.props.PanelHeight(),
- this.props.Document._fitWidth ?
- Math.max(NumCast(this.props.Document._height), NumCast(((this.props.Document.scrollHeight || 0) as number) * this.props.PanelWidth() / this.effectiveNativeWidth, this.props.PanelHeight())) :
- this.effectiveNativeHeight * this.nativeScaling
- );
+ return Math.min(this.props.PanelHeight(), Math.max(NumCast(this.layoutDoc.scrollHeight), this.effectiveNativeHeight) * this.nativeScaling);
}
return this.props.PanelHeight();
}
diff --git a/src/client/views/nodes/EquationBox.tsx b/src/client/views/nodes/EquationBox.tsx
index 5bc73d5d9..5bb904f91 100644
--- a/src/client/views/nodes/EquationBox.tsx
+++ b/src/client/views/nodes/EquationBox.tsx
@@ -1,18 +1,22 @@
import EquationEditor from 'equation-editor-react';
+import { action, reaction } from 'mobx';
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 { createSchema, makeInterface } from '../../../fields/Schema';
+import { NumCast, StrCast } from '../../../fields/Types';
import { TraceMobx } from '../../../fields/util';
-import { reaction, action } from 'mobx';
import { Docs } from '../../documents/Documents';
+import { ViewBoxBaseComponent } from '../DocComponent';
import { LightboxView } from '../LightboxView';
+import { FieldView, FieldViewProps } from './FieldView';
+import './LabelBox.scss';
+import functionPlot from "function-plot";
+import { DocumentManager } from '../../util/DocumentManager';
+import { Utils } from '../../../Utils';
+import { HeightSym, WidthSym } from '../../../fields/Doc';
+
const EquationSchema = createSchema({});
@@ -39,18 +43,29 @@ export class EquationBox extends ViewBoxBaseComponent<FieldViewProps, EquationDo
}
}, { fireImmediately: true });
}
+ plot: any;
@action
keyPressed = (e: KeyboardEvent) => {
const _height = Number(getComputedStyle(this._ref.current!.element.current).height.replace("px", ""));
const _width = Number(getComputedStyle(this._ref.current!.element.current).width.replace("px", ""));
- if (e.key === "Enter" || e.key === "Tab") {
+ if (e.key === "Enter") {
const nextEq = Docs.Create.EquationDocument({
title: "# math", text: StrCast(this.dataDoc.text), _width, _height: 25,
- x: NumCast(this.layoutDoc.x) + (e.key === "Tab" ? _width + 10 : 0), y: NumCast(this.layoutDoc.y) + (e.key === "Enter" ? _height + 10 : 0)
+ x: NumCast(this.layoutDoc.x), y: NumCast(this.layoutDoc.y) + _height + 10
});
EquationBox.SelectOnLoad = nextEq[Id];
this.props.addDocument?.(nextEq);
e.stopPropagation();
+
+ }
+ if (e.key === "Tab") {
+ const graph = Docs.Create.FunctionPlotDocument([this.rootDoc], {
+ x: NumCast(this.layoutDoc.x) + this.layoutDoc[WidthSym](),
+ y: NumCast(this.layoutDoc.y),
+ _width: 400, _height: 300, _backgroundColor: "white"
+ });
+ this.props.addDocument?.(graph);
+ e.stopPropagation();
}
if (e.key === "Backspace" && !this.dataDoc.text) this.props.removeDocument?.(this.rootDoc);
}
@@ -72,11 +87,11 @@ export class EquationBox extends ViewBoxBaseComponent<FieldViewProps, EquationDo
}}
>
<EquationEditor ref={this._ref}
- value={this.dataDoc.text || "y"}
+ value={this.dataDoc.text || "x"}
spaceBehavesLikeTab={true}
onChange={this.onChange}
autoCommands="pi theta sqrt sum prod alpha beta gamma rho"
- autoOperatorNames="sin cos tan" /></div>
- );
+ autoOperatorNames="sin cos tan" />
+ </div>);
}
} \ No newline at end of file
diff --git a/src/client/views/nodes/FunctionPlotBox.scss b/src/client/views/nodes/FunctionPlotBox.scss
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/src/client/views/nodes/FunctionPlotBox.scss
diff --git a/src/client/views/nodes/FunctionPlotBox.tsx b/src/client/views/nodes/FunctionPlotBox.tsx
new file mode 100644
index 000000000..dba08b506
--- /dev/null
+++ b/src/client/views/nodes/FunctionPlotBox.tsx
@@ -0,0 +1,76 @@
+import EquationEditor from 'equation-editor-react';
+import functionPlot from "function-plot";
+import { observer } from 'mobx-react';
+import * as React from 'react';
+import { documentSchema } from '../../../fields/documentSchemas';
+import { createSchema, makeInterface } from '../../../fields/Schema';
+import { StrCast } from '../../../fields/Types';
+import { TraceMobx } from '../../../fields/util';
+import { ViewBoxBaseComponent } from '../DocComponent';
+import { FieldView, FieldViewProps } from './FieldView';
+import './LabelBox.scss';
+import { DocListCast } from '../../../fields/Doc';
+import { computed } from 'mobx';
+
+
+const EquationSchema = createSchema({});
+
+type EquationDocument = makeInterface<[typeof EquationSchema, typeof documentSchema]>;
+const EquationDocument = makeInterface(EquationSchema, documentSchema);
+
+@observer
+export class FunctionPlotBox extends ViewBoxBaseComponent<FieldViewProps, EquationDocument>(EquationDocument) {
+ public static LayoutString(fieldKey: string) { return FieldView.LayoutString(FunctionPlotBox, fieldKey); }
+ public static GraphCount = 0;
+ _ref: React.RefObject<EquationEditor> = React.createRef();
+ _plot: any;
+ _plotId = "";
+ constructor(props: any) {
+ super(props);
+ this._plotId = "graph" + FunctionPlotBox.GraphCount++;
+ }
+ createGraph = (ele: HTMLDivElement) => {
+ let width = this.props.PanelWidth();
+ let height = this.props.PanelHeight();
+ const fn = StrCast(DocListCast(this.dataDoc.data).lastElement()?.text, "x^2").replace(/\\frac\{(.*)\}\{(.*)\}/, "($1/$2)");
+ console.log("Graphing:" + fn);
+ try {
+ this._plot = functionPlot({
+ target: "#" + ele.id,
+ width,
+ height,
+ yAxis: { domain: [-1, 9] },
+ grid: true,
+ data: [
+ {
+ fn,
+ // derivative: { fn: "2 * x", updateOnMouseMove: true }
+ }
+ ]
+ });
+ } catch (e) {
+ console.log(e);
+ }
+ }
+ @computed get theGraph() {
+ const fn = StrCast(DocListCast(this.dataDoc.data).lastElement()?.text, "x^2");
+ return <div id={`${this._plotId}`} ref={r => r && this.createGraph(r)} style={{ position: "absolute", width: "100%", height: "100%" }}
+ onPointerDown={e => e.stopPropagation()} />;
+ }
+ render() {
+ TraceMobx();
+ return (<div
+ style={{
+ pointerEvents: !this.active() ? "all" : undefined,
+ width: this.props.PanelWidth(),
+ height: this.props.PanelHeight()
+ }}
+ >
+ {this.theGraph}
+ <div style={{
+ display: this.props.isSelected() ? "none" : undefined, position: "absolute", width: "100%", height: "100%",
+ pointerEvents: "all"
+ }} />
+ </div>);
+ }
+} \ No newline at end of file