diff options
author | mehekj <mehek.jethani@gmail.com> | 2021-07-23 20:43:50 -0400 |
---|---|---|
committer | mehekj <mehek.jethani@gmail.com> | 2021-07-23 20:43:50 -0400 |
commit | 15041b8cd20bda206536b8d933672802c1a8cfc6 (patch) | |
tree | 39a395b1ca39e966162fbff22e753d2fb61fe06e /src | |
parent | 618062ac7c2349dbc25cc69d8683d6e29ed947e8 (diff) | |
parent | 14e66ac5bcdaa5e244be68ccb8cbb0c495917910 (diff) |
Merge branch 'master' into temporalmedia-mehek
Diffstat (limited to 'src')
87 files changed, 1140 insertions, 738 deletions
diff --git a/src/client/ClientRecommender.scss b/src/client/ClientRecommender.scss index 3f9102f15..178c7fdab 100644 --- a/src/client/ClientRecommender.scss +++ b/src/client/ClientRecommender.scss @@ -1,4 +1,4 @@ -// @import "/views/globalCssVariables.scss"; +// @import "/views/global/globalCssVariables.scss"; .space{ border: 1px dashed blue; diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts index 040571b10..c2cdf7f72 100644 --- a/src/client/documents/Documents.ts +++ b/src/client/documents/Documents.ts @@ -30,7 +30,7 @@ import { CollectionDockingView } from "../views/collections/CollectionDockingVie import { CollectionView, CollectionViewType } from "../views/collections/CollectionView"; import { ContextMenu } from "../views/ContextMenu"; import { ContextMenuProps } from "../views/ContextMenuItem"; -import { DFLT_IMAGE_NATIVE_DIM } from "../views/globalCssVariables.scss"; +import { DFLT_IMAGE_NATIVE_DIM } from "../views/global/globalCssVariables.scss"; import { ActiveArrowEnd, ActiveArrowStart, ActiveDash, ActiveFillColor, ActiveInkBezierApprox, ActiveInkColor, ActiveInkWidth, InkingStroke } from "../views/InkingStroke"; import { AudioBox } from "../views/nodes/AudioBox"; import { ColorBox } from "../views/nodes/ColorBox"; diff --git a/src/client/util/CaptureManager.scss b/src/client/util/CaptureManager.scss index 71539ee1e..a5024247e 100644 --- a/src/client/util/CaptureManager.scss +++ b/src/client/util/CaptureManager.scss @@ -1,4 +1,4 @@ -@import "../views/globalCssVariables"; +@import "../views/global/globalCssVariables"; .capture-interface { //background-color: whitesmoke !important; diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts index 5bab827d5..22504f102 100644 --- a/src/client/util/CurrentUserUtils.ts +++ b/src/client/util/CurrentUserUtils.ts @@ -405,14 +405,18 @@ export class CurrentUserUtils { selection: { type: "text", anchor: 1, head: 1 }, storedMarks: [] }; - const headerTemplate = Docs.Create.RTFDocument(new RichTextField(JSON.stringify(json), ""), { title: "header", version: headerViewVersion, target: doc, _height: 70, _headerPointerEvents: "all", _headerHeight: 12, _headerFontSize: 9, _autoHeight: true, system: true, cloneFieldFilter: new List<string>(["system"]) }, "header"); // text needs to be a space to allow templateText to be created + const headerTemplate = Docs.Create.RTFDocument(new RichTextField(JSON.stringify(json), ""), { + title: "text", version: headerViewVersion, target: doc, _height: 70, _headerPointerEvents: "all", + _headerHeight: 12, _headerFontSize: 9, _autoHeight: true, system: true, _fitWidth: true, + cloneFieldFilter: new List<string>(["system"]) + }, "header"); const headerBtnHgt = 10; headerTemplate[DataSym].layout = - "<div style='height:100%'>" + - ` <FormattedTextBox {...props} fieldKey={'text'} height='calc(100% - ${headerBtnHgt}px - {this._headerHeight}px)'/>` + - " <FormattedTextBox {...props} fieldKey={'header'} dontSelectOnLoad='true' ignoreAutoHeight='true' fontSize='{this._headerFontSize}px' height='{this._headerHeight||1}px' background={this._headerColor ||this.target.mySharedDocs.userColor||'lightGray'} />" + - ` <HTMLdiv fontSize='${headerBtnHgt - 1}' onClick={‘(this._headerHeight=Math.min(Math.max(1,this._height-30),this._headerHeight===1?50:1)) && (this._autoHeightMargins=this._headerHeight+${headerBtnHgt})’} height='${headerBtnHgt}px' background='yellow' >Metadata</HTMLdiv>` + - "</div>"; + "<HTMLdiv transformOrigin='top left' width='{100/scale}%' height='{100/scale}%' transform='scale({scale})'>" + + ` <FormattedTextBox {...props} dontScale='true' fieldKey={'text'} height='calc(100% - ${headerBtnHgt}px - {this._headerHeight}px)'/>` + + " <FormattedTextBox {...props} dontScale='true' fieldKey={'header'} dontSelectOnLoad='true' ignoreAutoHeight='true' fontSize='{this._headerFontSize}px' height='{(this._headerHeight||1)}px' background='{this._headerColor ||this.target.mySharedDocs.userColor||`lightGray`}' />" + + ` <HTMLdiv fontSize='${headerBtnHgt - 1}px' height='${headerBtnHgt}px' background='yellow' onClick={‘(this._headerHeight=scale*Math.min(Math.max(1,this._height-30),this._headerHeight===1?50:1)) && (this._autoHeightMargins=this._headerHeight+${headerBtnHgt})’} >Metadata</HTMLdiv>` + + "</HTMLdiv>"; // "<div style={'height:100%'}>" + // " <FormattedTextBox {...props} fieldKey={'header'} dontSelectOnLoad={'true'} ignoreAutoHeight={'true'} pointerEvents='{this._headerPointerEvents||`none`}' fontSize='{this._headerFontSize}px' height='{this._headerHeight}px' background='{this._headerColor||this.target.mySharedDocs.userColor}' />" + diff --git a/src/client/util/DragManager.ts b/src/client/util/DragManager.ts index 88bf6f36d..07b2b7dff 100644 --- a/src/client/util/DragManager.ts +++ b/src/client/util/DragManager.ts @@ -9,7 +9,7 @@ import { ScriptField } from "../../fields/ScriptField"; import { Cast, NumCast, ScriptCast, StrCast } from "../../fields/Types"; import { emptyFunction, returnTrue } from "../../Utils"; import { Docs, DocUtils } from "../documents/Documents"; -import * as globalCssVariables from "../views/globalCssVariables.scss"; +import * as globalCssVariables from "../views/global/globalCssVariables.scss"; import { UndoManager } from "./UndoManager"; import { SnappingManager } from "./SnappingManager"; import { DocumentView } from "../views/nodes/DocumentView"; diff --git a/src/client/util/InteractionUtils.tsx b/src/client/util/InteractionUtils.tsx index 01d00db30..ba935e3bf 100644 --- a/src/client/util/InteractionUtils.tsx +++ b/src/client/util/InteractionUtils.tsx @@ -208,7 +208,7 @@ export namespace InteractionUtils { <polyline points={strpts} style={{ - filter: drawHalo ? "url(#inkSelectionHalo)" : undefined, + // filter: drawHalo ? "url(#inkSelectionHalo)" : undefined, fill: fill ? fill : "none", opacity: strokeWidth !== width ? 0.5 : undefined, pointerEvents: pevents as any, diff --git a/src/client/util/SettingsManager.scss b/src/client/util/SettingsManager.scss index d8342ea56..c9db94419 100644 --- a/src/client/util/SettingsManager.scss +++ b/src/client/util/SettingsManager.scss @@ -1,4 +1,4 @@ -@import "../views/globalCssVariables"; +@import "../views/global/globalCssVariables"; .settings-interface { //background-color: whitesmoke !important; @@ -264,7 +264,7 @@ //margin-top: 4px; &:hover { - background: $main-accent; + background: $medium-gray; } } diff --git a/src/client/views/AntimodeMenu.scss b/src/client/views/AntimodeMenu.scss index a275901be..2bac03af4 100644 --- a/src/client/views/AntimodeMenu.scss +++ b/src/client/views/AntimodeMenu.scss @@ -1,11 +1,11 @@ -@import "./globalCssVariables"; +@import "./global/globalCssVariables"; .antimodeMenu-cont { position: absolute; z-index: 10001; height: $antimodemenu-height; - background: #323232; + background: $dark-gray; box-shadow: 3px 3px 3px rgba(0, 0, 0, 0.25); // border-radius: 0px 6px 6px 6px; z-index: 1001; diff --git a/src/client/views/ContextMenu.scss b/src/client/views/ContextMenu.scss index b514de5f2..795529780 100644 --- a/src/client/views/ContextMenu.scss +++ b/src/client/views/ContextMenu.scss @@ -1,10 +1,10 @@ -@import "globalCssVariables"; +@import "global/globalCssVariables"; .contextMenu-cont { position: absolute; display: flex; z-index: $contextMenu-zindex; - box-shadow: $intermediate-color 0.2vw 0.2vw 0.4vw; + box-shadow: $medium-gray 0.2vw 0.2vw 0.4vw; flex-direction: column; background: whitesmoke; padding-top: 10px; @@ -14,17 +14,17 @@ } // .contextMenu-item:first-child { -// background: $intermediate-color; -// color: $light-color; +// background: $medium-gray; +// color: $white; // } // .contextMenu-item:first-child::placeholder { -// color: $light-color; +// color: $white; // } // .contextMenu-item:first-child:hover { -// background: $intermediate-color; -// color: $light-color; +// background: $medium-gray; +// color: $white; // } .contextMenu-subMenu-cont { @@ -94,7 +94,7 @@ .contextMenu-item:hover { border-width: .11px; border-style: none; - border-color: $intermediate-color; // rgb(187, 186, 186); + border-color: $medium-gray; // rgb(187, 186, 186); border-bottom-style: solid; border-top-style: solid; @@ -122,7 +122,7 @@ transition: all .1s; border-width: .11px; border-style: none; - border-color: $intermediate-color; // rgb(187, 186, 186); + border-color: $medium-gray; // rgb(187, 186, 186); // padding: 10px 0px 10px 0px; white-space: nowrap; font-size: 13px; @@ -137,7 +137,7 @@ .contextMenu-item:hover { transition: all 0.1s ease; - background: $lighter-alt-accent; + background: $light-blue; } .contextMenu-description { diff --git a/src/client/views/DocComponent.tsx b/src/client/views/DocComponent.tsx index da8af7cc0..0b70ce68d 100644 --- a/src/client/views/DocComponent.tsx +++ b/src/client/views/DocComponent.tsx @@ -119,7 +119,7 @@ export function ViewBoxAnnotatableComponent<P extends ViewBoxAnnotatableProps, T styleFromLayoutString = (scale: number) => { const style: { [key: string]: any } = {}; - const divKeys = ["width", "height", "fontSize", "left", "background", "left", "right", "top", "bottom", "pointerEvents", "position"]; + const divKeys = ["width", "height", "fontSize", "transform", "left", "background", "left", "right", "top", "bottom", "pointerEvents", "position"]; const replacer = (match: any, expr: string, offset: any, string: any) => { // bcz: this executes a script to convert a property expression string: { script } into a value return ScriptField.MakeFunction(expr, { self: Doc.name, this: Doc.name, scale: "number" })?.script.run({ self: this.rootDoc, this: this.layoutDoc, scale }).result as string || ""; }; diff --git a/src/client/views/DocumentButtonBar.scss b/src/client/views/DocumentButtonBar.scss index 09ae14016..2a0b494f5 100644 --- a/src/client/views/DocumentButtonBar.scss +++ b/src/client/views/DocumentButtonBar.scss @@ -1,4 +1,4 @@ -@import "globalCssVariables"; +@import "global/globalCssVariables"; $linkGap : 3px; @@ -7,13 +7,13 @@ $linkGap : 3px; } .documentButtonBar-linkButton-empty:hover { - background: $main-accent; + background: $medium-gray; transform: scale(1.05); cursor: pointer; } .documentButtonBar-linkButton-nonempty:hover { - background: $main-accent; + background: $medium-gray; transform: scale(1.05); cursor: pointer; } @@ -25,8 +25,8 @@ $linkGap : 3px; border-radius: 50%; opacity: 0.9; pointer-events: auto; - background-color: $dark-color; - color: $light-color; + background-color: $dark-gray; + color: $white; text-transform: uppercase; letter-spacing: 2px; font-size: 75%; @@ -37,7 +37,7 @@ $linkGap : 3px; align-items: center; &:hover { - background: $main-accent; + background: $medium-gray; transform: scale(1.05); cursor: pointer; } @@ -64,12 +64,12 @@ $linkGap : 3px; text-align: center; border-radius: 50%; pointer-events: auto; - background-color: $dark-color; + background-color: $dark-gray; border: none; transition: 0.2s ease all; &:hover { - background-color: $main-accent; + background-color: $medium-gray; } } diff --git a/src/client/views/DocumentDecorations.scss b/src/client/views/DocumentDecorations.scss index db2d56aa8..1715f35e7 100644 --- a/src/client/views/DocumentDecorations.scss +++ b/src/client/views/DocumentDecorations.scss @@ -1,4 +1,4 @@ -@import "globalCssVariables"; +@import "global/globalCssVariables"; $linkGap : 3px; @@ -49,7 +49,7 @@ $linkGap : 3px; .documentDecorations-bottomResizer, .documentDecorations-rightResizer { pointer-events: auto; - background: $alt-accent; + background: $medium-gray; opacity: 0.1; &:hover { opacity: 1; @@ -251,13 +251,13 @@ $linkGap : 3px; } .linkButton-empty:hover { - background: $main-accent; + background: $medium-gray; transform: scale(1.05); cursor: pointer; } .linkButton-nonempty:hover { - background: $main-accent; + background: $medium-gray; transform: scale(1.05); cursor: pointer; } @@ -271,7 +271,7 @@ $linkGap : 3px; flex-direction: row; z-index: 998; position: absolute; - background: $alt-accent; + background: $medium-gray; } .linkButtonWrapper { @@ -286,8 +286,8 @@ $linkGap : 3px; text-align: center; border-radius: 50%; pointer-events: auto; - color: $dark-color; - border: $dark-color 1px solid; + color: $dark-gray; + border: $dark-gray 1px solid; } .linkButton-linker:hover { @@ -302,8 +302,8 @@ $linkGap : 3px; border-radius: 50%; opacity: 0.9; pointer-events: auto; - background-color: $dark-color; - color: $light-color; + background-color: $dark-gray; + color: $white; text-transform: uppercase; letter-spacing: 2px; font-size: 75%; @@ -314,7 +314,7 @@ $linkGap : 3px; align-items: center; &:hover { - background: $main-accent; + background: $medium-gray; transform: scale(1.05); cursor: pointer; } @@ -343,13 +343,13 @@ $linkGap : 3px; border-radius: 50%; opacity: 0.9; font-size: 14; - background-color: $dark-color; - color: $light-color; + background-color: $dark-gray; + color: $white; text-align: center; cursor: pointer; &:hover { - background: $main-accent; + background: $medium-gray; transform: scale(1.05); } } @@ -365,7 +365,7 @@ $linkGap : 3px; width: max-content; font-family: $sans-serif; font-size: 12px; - background-color: $light-color-secondary; + background-color: $light-gray; padding: 2px 12px; list-style: none; diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 65a97a49d..d24ab974c 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -201,7 +201,7 @@ export class DocumentDecorations extends React.Component<{ boundsLeft: number, b (e: PointerEvent, down: number[], delta: number[]) => { const movement = { X: delta[0], Y: e.clientY - down[1] }; const angle = Math.max(1, Math.abs(movement.Y / 10)); - InkStrokeProperties.Instance?.rotate(2 * movement.X / angle * (Math.PI / 180)); + InkStrokeProperties.Instance?.rotateInk(2 * movement.X / angle * (Math.PI / 180)); return false; }, () => this._rotateUndo?.end(), diff --git a/src/client/views/GlobalKeyHandler.ts b/src/client/views/GlobalKeyHandler.ts index c4162a6bb..76eb4c142 100644 --- a/src/client/views/GlobalKeyHandler.ts +++ b/src/client/views/GlobalKeyHandler.ts @@ -114,7 +114,7 @@ export class KeyManager { case "escape": DocumentLinksButton.StartLink = undefined; DocumentLinksButton.StartLinkView = undefined; - InkStrokeProperties.Instance && (InkStrokeProperties.Instance._controlBtn = false); + InkStrokeProperties.Instance && (InkStrokeProperties.Instance._controlButton = false); CurrentUserUtils.SelectedTool = InkTool.None; var doDeselect = true; if (SnappingManager.GetIsDragging()) { diff --git a/src/client/views/InkControls.tsx b/src/client/views/InkControls.tsx new file mode 100644 index 000000000..23f22c774 --- /dev/null +++ b/src/client/views/InkControls.tsx @@ -0,0 +1,135 @@ +import React = require("react"); +import { observable, action } from "mobx"; +import { observer } from "mobx-react"; +import { InkStrokeProperties } from "./InkStrokeProperties"; +import { setupMoveUpEvents, emptyFunction } from "../../Utils"; +import { UndoManager } from "../util/UndoManager"; +import { ControlPoint, InkData, PointData } from "../../fields/InkField"; +import { Transform } from "../util/Transform"; + +export interface InkControlProps { + data: InkData; + addedPoints: PointData[]; + format: number[]; + ScreenToLocalTransform: () => Transform; +} + +@observer +export class InkControls extends React.Component<InkControlProps> { + @observable private _overControl = -1; + @observable private _overAddPoint = -1; + + /** + * Handles the movement of a selected control point when the user clicks and drags. + * @param controlIndex The index of the currently selected control point. + */ + @action + onControlDown = (e: React.PointerEvent, controlIndex: number): void => { + if (InkStrokeProperties.Instance) { + InkStrokeProperties.Instance.moveControl(0, 0, 1); + const controlUndo = UndoManager.StartBatch("DocDecs set radius"); + const screenScale = this.props.ScreenToLocalTransform().Scale; + const order = controlIndex % 4; + const handleIndexA = order === 2 ? controlIndex - 1 : controlIndex - 2; + const handleIndexB = order === 2 ? controlIndex + 2 : controlIndex + 1; + setupMoveUpEvents(this, e, + (e: PointerEvent, down: number[], delta: number[]) => { + InkStrokeProperties.Instance?.moveControl(-delta[0] * screenScale, -delta[1] * screenScale, controlIndex); + return false; + }, + () => controlUndo?.end(), + emptyFunction); + // action((e: PointerEvent, doubleTap: boolean | undefined) => + // { if (doubleTap && InkStrokeProperties.Instance?._brokenIndices.includes(controlIndex)) { + // InkStrokeProperties.Instance?.snapHandleTangent(controlIndex, handleIndexA, handleIndexB); + // }})); + } + } + + /** + * Deletes the currently selected point. + */ + @action + onDelete = (e: KeyboardEvent) => { + if (["-", "Backspace", "Delete"].includes(e.key)) { + if (InkStrokeProperties.Instance?.deletePoints()) e.stopPropagation(); + } + } + + /** + * Changes the current selected control point. + */ + @action + changeCurrPoint = (i: number) => { + if (InkStrokeProperties.Instance) { + InkStrokeProperties.Instance._currentPoint = i; + document.addEventListener("keydown", this.onDelete, true); + } + } + + /** + * Updates whether a user has hovered over a particular control point or point that could be added + * on click. + */ + @action onEnterControl = (i: number) => { this._overControl = i; }; + @action onLeaveControl = () => { this._overControl = -1; }; + @action onEnterAddPoint = (i: number) => { this._overAddPoint = i; }; + @action onLeaveAddPoint = () => { this._overAddPoint = -1; }; + + render() { + const formatInstance = InkStrokeProperties.Instance; + if (!formatInstance) return (null); + + // Accessing the current ink's data and extracting all control points. + const data = this.props.data; + const controlPoints: ControlPoint[] = []; + if (data.length >= 4) { + for (let i = 0; i <= data.length - 4; i += 4) { + controlPoints.push({ X: data[i].X, Y: data[i].Y, I: i }); + controlPoints.push({ X: data[i + 3].X, Y: data[i + 3].Y, I: i + 3 }); + } + } + const addedPoints = this.props.addedPoints; + const [left, top, scaleX, scaleY, strokeWidth, dotsize] = this.props.format; + + return ( + <> + {addedPoints.map((pts, i) => + <svg height="10" width="10" key={`add${i}`}> + <circle + cx={(pts.X - left - strokeWidth / 2) * scaleX + strokeWidth / 2} + cy={(pts.Y - top - strokeWidth / 2) * scaleY + strokeWidth / 2} + r={strokeWidth / 2} + stroke={this._overAddPoint === i ? "#1F85DE" : "transparent"} + strokeWidth={dotsize / 4} fill={this._overAddPoint === i ? "#1F85DE" : "transparent"} + onPointerDown={() => { formatInstance?.addPoints(pts.X, pts.Y, addedPoints, i, controlPoints); }} + onMouseEnter={() => this.onEnterAddPoint(i)} + onMouseLeave={this.onLeaveAddPoint} + pointerEvents="all" + cursor="all-scroll" + /> + </svg> + )} + {controlPoints.map((control, i) => + <svg height="10" width="10" key={`ctrl${i}`}> + <rect + x={(control.X - left - strokeWidth / 2) * scaleX} + y={(control.Y - top - strokeWidth / 2) * scaleY} + height={this._overControl === i ? strokeWidth * 1.5 : strokeWidth} + width={this._overControl === i ? strokeWidth * 1.5 : strokeWidth} + strokeWidth={strokeWidth / 6} stroke="#1F85DE" + fill={formatInstance?._currentPoint === control.I ? "#1F85DE" : "white"} + onPointerDown={(e) => { + this.changeCurrPoint(control.I); + this.onControlDown(e, control.I); }} + onMouseEnter={() => this.onEnterControl(i)} + onMouseLeave={this.onLeaveControl} + pointerEvents="all" + cursor="default" + /> + </svg> + )} + </> + ); + } +}
\ No newline at end of file diff --git a/src/client/views/InkHandles.tsx b/src/client/views/InkHandles.tsx new file mode 100644 index 000000000..28b6dd820 --- /dev/null +++ b/src/client/views/InkHandles.tsx @@ -0,0 +1,122 @@ +import React = require("react"); +import { observable, action } from "mobx"; +import { observer } from "mobx-react"; +import { InkStrokeProperties } from "./InkStrokeProperties"; +import { setupMoveUpEvents, emptyFunction } from "../../Utils"; +import { UndoManager } from "../util/UndoManager"; +import { InkData, HandlePoint, HandleLine } from "../../fields/InkField"; +import { Transform } from "../util/Transform"; +import { Doc } from "../../fields/Doc"; +import { listSpec } from "../../fields/Schema"; +import { List } from "../../fields/List"; +import { Cast } from "../../fields/Types"; + +export interface InkHandlesProps { + inkDoc: Doc; + data: InkData; + format: number[]; + ScreenToLocalTransform: () => Transform; +} + +@observer +export class InkHandles extends React.Component<InkHandlesProps> { + /** + * Handles the movement of a selected handle point when the user clicks and drags. + * @param handleNum The index of the currently selected handle point. + */ + onHandleDown = (e: React.PointerEvent, handleIndex: number): void => { + if (InkStrokeProperties.Instance) { + InkStrokeProperties.Instance.moveControl(0, 0, 1); + const controlUndo = UndoManager.StartBatch("DocDecs set radius"); + const screenScale = this.props.ScreenToLocalTransform().Scale; + const order = handleIndex % 4; + const oppositeHandleIndex = order === 1 ? handleIndex - 3 : handleIndex + 3; + const controlIndex = order === 1 ? handleIndex - 1 : handleIndex + 2; + document.addEventListener("keydown", (e: KeyboardEvent) => this.onBreakTangent(e, controlIndex), true); + setupMoveUpEvents(this, e, (e: PointerEvent, down: number[], delta: number[]) => { + InkStrokeProperties.Instance?.moveHandle(-delta[0] * screenScale, -delta[1] * screenScale, handleIndex, oppositeHandleIndex, controlIndex); + return false; + }, () => controlUndo?.end(), emptyFunction + ); + } + } + + /** + * Breaks tangent handle movement when ‘Alt’ key is held down. Adds the current handle index and + * its matching (opposite) handle to a list of broken handle indices. + * @param handleNum The index of the currently selected handle point. + */ + @action + onBreakTangent = (e: KeyboardEvent, controlIndex: number) => { + const doc: Doc = this.props.inkDoc; + if (["Alt"].includes(e.key)) { + if (doc) { + const brokenIndices = Cast(doc.brokenInkIndices, listSpec("number")) || new List; + if (brokenIndices && !brokenIndices.includes(controlIndex)) { + brokenIndices.push(controlIndex); + } + doc.brokenInkIndices = brokenIndices; + } + } + } + + render() { + const formatInstance = InkStrokeProperties.Instance; + if (!formatInstance) return (null); + + // Accessing the current ink's data and extracting all handle points and handle lines. + const data = this.props.data; + const handlePoints: HandlePoint[] = []; + const handleLines: HandleLine[] = []; + if (data.length >= 4) { + for (let i = 0; i <= data.length - 4; i += 4) { + handlePoints.push({ X: data[i + 1].X, Y: data[i + 1].Y, I: i + 1, dot1: i, dot2: i === 0 ? i : i - 1 }); + handlePoints.push({ X: data[i + 2].X, Y: data[i + 2].Y, I: i + 2, dot1: i + 3, dot2: i === data.length ? i + 3 : i + 4 }); + } + // Adding first and last (single) handle lines. + handleLines.push({ X1: data[0].X, Y1: data[0].Y, X2: data[0].X, Y2: data[0].Y, X3: data[1].X, Y3: data[1].Y, dot1: 0, dot2: 0 }); + handleLines.push({ X1: data[data.length - 2].X, Y1: data[data.length - 2].Y, X2: data[data.length - 1].X, Y2: data[data.length - 1].Y, X3: data[data.length - 1].X, Y3: data[data.length - 1].Y, dot1: data.length - 1, dot2: data.length - 1 }); + for (let i = 2; i < data.length - 4; i += 4) { + handleLines.push({ X1: data[i].X, Y1: data[i].Y, X2: data[i + 1].X, Y2: data[i + 1].Y, X3: data[i + 3].X, Y3: data[i + 3].Y, dot1: i + 1, dot2: i + 2 }); + } + } + const [left, top, scaleX, scaleY, strokeWidth, dotsize] = this.props.format; + + return ( + <> + {handlePoints.map((pts, i) => + <svg height="10" width="10" key={`hdl${i}`}> + <circle + cx={(pts.X - left - strokeWidth / 2) * scaleX + strokeWidth / 2} + cy={(pts.Y - top - strokeWidth / 2) * scaleY + strokeWidth / 2} + r={strokeWidth / 2} + strokeWidth={0} + fill="#1F85DE" + onPointerDown={(e) => this.onHandleDown(e, pts.I)} + pointerEvents="all" + cursor="default" + display={(pts.dot1 === formatInstance._currentPoint || pts.dot2 === formatInstance._currentPoint) ? "inherit" : "none"} /> + </svg>)} + {handleLines.map((pts, i) => + <svg height="100" width="100" key={`line${i}`}> + <line + x1={(pts.X1 - left - strokeWidth / 2) * scaleX + strokeWidth / 2} + y1={(pts.Y1 - top - strokeWidth / 2) * scaleY + strokeWidth / 2} + x2={(pts.X2 - left - strokeWidth / 2) * scaleX + strokeWidth / 2} + y2={(pts.Y2 - top - strokeWidth / 2) * scaleY + strokeWidth / 2} + stroke="#1F85DE" + strokeWidth={dotsize / 8} + display={(pts.dot1 === formatInstance._currentPoint || pts.dot2 === formatInstance._currentPoint) ? "inherit" : "none"} /> + <line + x1={(pts.X2 - left - strokeWidth / 2) * scaleX + strokeWidth / 2} + y1={(pts.Y2 - top - strokeWidth / 2) * scaleY + strokeWidth / 2} + x2={(pts.X3 - left - strokeWidth / 2) * scaleX + strokeWidth / 2} + y2={(pts.Y3 - top - strokeWidth / 2) * scaleY + strokeWidth / 2} + stroke="#1F85DE" + strokeWidth={dotsize / 8} + display={(pts.dot1 === formatInstance._currentPoint || pts.dot2 === formatInstance._currentPoint) ? "inherit" : "none"} /> + </svg>)} + </> + ); + } +}
\ No newline at end of file diff --git a/src/client/views/InkStroke.scss b/src/client/views/InkStroke.scss new file mode 100644 index 000000000..812a79bd5 --- /dev/null +++ b/src/client/views/InkStroke.scss @@ -0,0 +1,11 @@ +.inkStroke { + mix-blend-mode: multiply; + stroke-linejoin: round; + stroke-linecap: round; + overflow: visible !important; + transform-origin: top left; + + svg:not(:root) { + overflow: visible !important; + } +} diff --git a/src/client/views/InkStrokeProperties.ts b/src/client/views/InkStrokeProperties.ts index b13b04f68..1a3585f3e 100644 --- a/src/client/views/InkStrokeProperties.ts +++ b/src/client/views/InkStrokeProperties.ts @@ -1,124 +1,44 @@ import { action, computed, observable } from "mobx"; -import { ColorState } from 'react-color'; -import { Doc, Field, Opt } from "../../fields/Doc"; +import { Doc, DocListCast, Field, Opt } from "../../fields/Doc"; import { Document } from "../../fields/documentSchemas"; -import { InkField, InkData } from "../../fields/InkField"; +import { InkField, InkData, PointData, ControlPoint } from "../../fields/InkField"; +import { List } from "../../fields/List"; +import { listSpec } from "../../fields/Schema"; import { Cast, NumCast } from "../../fields/Types"; import { DocumentType } from "../documents/DocumentTypes"; import { SelectionManager } from "../util/SelectionManager"; import { undoBatch } from "../util/UndoManager"; -import { bool } from "sharp"; export class InkStrokeProperties { static Instance: InkStrokeProperties | undefined; - private _lastFill = "#D0021B"; - private _lastLine = "#D0021B"; - private _lastDash = "2"; - private _inkDocs: { x: number, y: number, width: number, height: number }[] = []; - @observable _lock = false; - @observable _controlBtn = false; - @observable _currPoint = -1; + @observable _controlButton = false; + @observable _currentPoint = -1; - getField(key: string) { - return this.selectedInk?.reduce((p, i) => - (p === undefined || (p && p === i.rootDoc[key])) && i.rootDoc[key] !== "0" ? Field.toString(i.rootDoc[key] as Field) : "", undefined as Opt<string>); + constructor() { + InkStrokeProperties.Instance = this; } @computed get selectedInk() { const inks = SelectionManager.Views().filter(i => Document(i.rootDoc).type === DocumentType.INK); return inks.length ? inks : undefined; } - @computed get unFilled() { return this.selectedInk?.reduce((p, i) => p && !i.rootDoc.fillColor ? true : false, true) || false; } - @computed get unStrokd() { return this.selectedInk?.reduce((p, i) => p && !i.rootDoc.color ? true : false, true) || false; } - @computed get solidFil() { return this.selectedInk?.reduce((p, i) => p && i.rootDoc.fillColor ? true : false, true) || false; } - @computed get solidStk() { return this.selectedInk?.reduce((p, i) => p && i.rootDoc.color && (!i.rootDoc.strokeDash || i.rootDoc.strokeDash === "0") ? true : false, true) || false; } - @computed get dashdStk() { return !this.unStrokd && this.getField("strokeDash") || ""; } - @computed get colorFil() { const ccol = this.getField("fillColor") || ""; ccol && (this._lastFill = ccol); return ccol; } - @computed get colorStk() { const ccol = this.getField("color") || ""; ccol && (this._lastLine = ccol); return ccol; } - @computed get widthStk() { return this.getField("strokeWidth") || "1"; } - @computed get markHead() { return this.getField("strokeStartMarker") || ""; } - @computed get markTail() { return this.getField("strokeEndMarker") || ""; } - @computed get shapeHgt() { return this.getField("_height"); } - @computed get shapeWid() { return this.getField("_width"); } - @computed get shapeXps() { return this.getField("x"); } - @computed get shapeYps() { return this.getField("y"); } - @computed get shapeRot() { return this.getField("rotation"); } - set unFilled(value) { this.colorFil = value ? "" : this._lastFill; } - set solidFil(value) { this.unFilled = !value; } - set colorFil(value) { value && (this._lastFill = value); this.selectedInk?.forEach(i => i.rootDoc.fillColor = value ? value : undefined); } - set colorStk(value) { value && (this._lastLine = value); this.selectedInk?.forEach(i => i.rootDoc.color = value ? value : undefined); } - set markHead(value) { this.selectedInk?.forEach(i => i.rootDoc.strokeStartMarker = value); } - set markTail(value) { this.selectedInk?.forEach(i => i.rootDoc.strokeEndMarker = value); } - set unStrokd(value) { this.colorStk = value ? "" : this._lastLine; } - set solidStk(value) { this.dashdStk = ""; this.unStrokd = !value; } - set dashdStk(value) { - value && (this._lastDash = value) && (this.unStrokd = false); - this.selectedInk?.forEach(i => i.rootDoc.strokeDash = value ? this._lastDash : undefined); - } - set shapeXps(value) { this.selectedInk?.forEach(i => i.rootDoc.x = Number(value)); } - set shapeYps(value) { this.selectedInk?.forEach(i => i.rootDoc.y = Number(value)); } - set shapeRot(value) { this.selectedInk?.forEach(i => i.rootDoc.rotation = Number(value)); } - set widthStk(value) { this.selectedInk?.forEach(i => i.rootDoc.strokeWidth = Number(value)); } - set shapeWid(value) { - this.selectedInk?.filter(i => i.rootDoc._width && i.rootDoc._height).forEach(i => { - const oldWidth = NumCast(i.rootDoc._width); - i.rootDoc._width = Number(value); - this._lock && (i.rootDoc._height = (i.rootDoc._width * NumCast(i.rootDoc._height)) / oldWidth); - }); - } - set shapeHgt(value) { - this.selectedInk?.filter(i => i.rootDoc._width && i.rootDoc._height).forEach(i => { - const oldHeight = NumCast(i.rootDoc._height); - i.rootDoc._height = Number(value); - this._lock && (i.rootDoc._width = (i.rootDoc._height * NumCast(i.rootDoc._width)) / oldHeight); - }); - } - - constructor() { - InkStrokeProperties.Instance = this; - } - - @undoBatch - @action - addPoints = (x: number, y: number, pts: { X: number, Y: number }[], index: number, control: { X: number, Y: number }[]) => { - this.selectedInk?.forEach(action(inkView => { - if (this.selectedInk?.length === 1) { - const doc = Document(inkView.rootDoc); - if (doc.type === DocumentType.INK) { - const ink = Cast(doc.data, InkField)?.inkData; - if (ink) { - const newPoints: { X: number, Y: number }[] = []; - var counter = 0; - for (var k = 0; k < index; k++) { - control.forEach(pt => (pts[k].X === pt.X && pts[k].Y === pt.Y) && counter++); - } - //decide where to put the new coordinate - const spNum = Math.floor(counter / 2) * 4 + 2; - - for (var i = 0; i < spNum; i++) { - ink[i] && newPoints.push({ X: ink[i].X, Y: ink[i].Y }); - } - for (var j = 0; j < 4; j++) { - newPoints.push({ X: x, Y: y }); - } - for (var i = spNum; i < ink.length; i++) { - newPoints.push({ X: ink[i].X, Y: ink[i].Y }); - } - this._currPoint = -1; - Doc.GetProto(doc).data = new InkField(newPoints); - } - } - } - })); + getField(key: string) { + return this.selectedInk?.reduce((p, i) => + (p === undefined || (p && p === i.rootDoc[key])) && i.rootDoc[key] !== "0" ? Field.toString(i.rootDoc[key] as Field) : "", undefined as Opt<string>); } - applyFunction = (func: (doc: Doc, ink: InkData, ptsXscale: number, ptsYscale: number) => { X: number, Y: number }[] | undefined, requireCurrPoint: boolean = false) => { + /** + * Helper function that enables other functions to be applied to a particular ink instance. + * @param func The inputted function. + * @param requireCurrPoint Indicates whether the current selected point is needed. + */ + applyFunction = (func: (doc: Doc, ink: InkData, ptsXscale: number, ptsYscale: number) => { X: number, Y: number }[] | undefined, requireCurrPoint: boolean = false) => { var appliedFunc = false; this.selectedInk?.forEach(action(inkView => { - if (this.selectedInk?.length === 1 && (!requireCurrPoint || this._currPoint !== -1)) { + if (this.selectedInk?.length === 1 && (!requireCurrPoint || this._currentPoint !== -1)) { const doc = Document(inkView.rootDoc); if (doc.type === DocumentType.INK && doc.width && doc.height) { const ink = Cast(doc.data, InkField)?.inkData; @@ -145,17 +65,136 @@ export class InkStrokeProperties { return appliedFunc; } + /** + * Adds a new control point to the ink instance when editing its format. + * @param index The index of the new point. + * @param control The list of all control points of the ink. + */ + @undoBatch + @action + addPoints = (x: number, y: number, points: InkData, index: number, controls: { X: number, Y: number }[]) => { + this.applyFunction((doc: Doc, ink: InkData) => { + const newControl = { X: x, Y: y }; + const newPoints: InkData = []; + let [counter, start, end] = [0, 0, 0]; + for (let k = 0; k < points.length; k++) { + if (end === 0) { + controls.forEach((control) => { + if (control.X === points[k].X && control.Y === points[k].Y) { + if (k < index) { + counter++; + start = k; + } else if (k > index) { + end = k; + } + } + }); + } + } + if (end === 0) end = points.length-1; + // Index of new control point with regards to the ink data. + const newIndex = Math.floor(counter / 2) * 4 + 2; + // Creating new ink data with the new control point and handle points inputted. + for (let i = 0; i < ink.length; i++) { + if (i === newIndex) { + const [handleA, handleB] = this.getNewHandlePoints(points.slice(start, index+1), points.slice(index, end), newControl); + newPoints.push(handleA, newControl, newControl, handleB); + // Adjusting the magnitude of the left handle line of the right neighboring control point. + const [rightControl, rightHandle] = [points[end], ink[i]]; + const scaledVector = this.getScaledHandlePoint(false, start, end, index, rightControl, rightHandle); + rightHandle && newPoints.push({ X: rightControl.X - scaledVector.X, Y: rightControl.Y - scaledVector.Y }); + } else if (i === newIndex - 1) { + // Adjusting the magnitude of the right handle line of the left neighboring control point. + const [leftControl, leftHandle] = [points[start], ink[i]]; + const scaledVector = this.getScaledHandlePoint(true, start, end, index, leftControl, leftHandle); + leftHandle && newPoints.push({ X: leftControl.X - scaledVector.X, Y: leftControl.Y - scaledVector.Y }); + } else { + ink[i] && newPoints.push({ X: ink[i].X, Y: ink[i].Y }); + } + + } + let brokenIndices = Cast(doc.brokenInkIndices, listSpec("number")); + // Updating the indices of the control points whose handle tangency has been broken. + if (brokenIndices) { + brokenIndices = new List(brokenIndices.map((control) => { + if (control >= newIndex) { + return control + 4; + } else { + return control; + } + })); + } + doc.brokenInkIndices = brokenIndices; + this._currentPoint = -1; + return newPoints; + }); + } + + /** + * Scales a handle point of a control point that is adjacent to a newly added one. + * @param isLeft Determines if the current control point is on the left or right side of the newly added one. + * @param start Beginning index of curve from the left control point to the newly added one. + * @param end Final index of curve from the newly added control point to its right neighbor. + */ + getScaledHandlePoint(isLeft: boolean, start: number, end: number, index: number, control: PointData, handle: PointData) { + const prevSize = end - start; + const newSize = isLeft ? index - start : end - index; + const handleVector = { X: control.X - handle.X, Y: control.Y - handle.Y }; + const scaledVector = { X: handleVector.X * (newSize / prevSize), Y: handleVector.Y * (newSize / prevSize) }; + return scaledVector; + } + + /** + * Determines the position of the handle points of a newly added control point by finding the + * tangent vectors to the split curve at the new control. Given the properties of Bézier curves, + * the tangent vector to a control point is equivalent to the first/last (depending on the direction + * of the curve) leg of the Bézier curve's derivative. + * (Source: https://pages.mtu.edu/~shene/COURSES/cs3621/NOTES/spline/Bezier/bezier-der.html) + * + * @param C The curve represented by all points from the previous control until the newly added point. + * @param D The curve represented by all points from the newly added point to the next control. + * @param newControl The newly added control point. + */ + getNewHandlePoints = (C: PointData[], D: PointData[], newControl: PointData) => { + const [m, n] = [C.length, D.length]; + let handleSizeA = Math.sqrt((Math.pow(newControl.X - C[0].X, 2)) + (Math.pow(newControl.Y - C[0].Y, 2))); + let handleSizeB = Math.sqrt((Math.pow(D[n-1].X - newControl.X, 2)) + (Math.pow(D[n-1].Y - newControl.Y, 2))); + // Scaling adjustments to improve the ratio between the magnitudes of the two handle lines. + // (Ensures that the new point added doesn't augment the inital shape of the curve much). + if (handleSizeA < 75 && handleSizeB < 75) { + handleSizeA *= 3; + handleSizeB *= 3; + } + if (Math.abs(handleSizeA - handleSizeB) < 50) { + handleSizeA *= 5; + handleSizeB *= 5; + } else if (Math.abs(handleSizeA - handleSizeB) < 150) { + handleSizeA *= 2; + handleSizeB *= 2; + } + // Finding the last leg of the derivative curve of C. + const dC = { X: (handleSizeA / n) * (C[m-1].X - C[m-2].X), Y: (handleSizeA / n) * (C[m-1].Y - C[m-2].Y) }; + // Finding the first leg of the derivative curve of D. + const dD = { X: (handleSizeB / m) * (D[1].X - D[0].X), Y: (handleSizeB / m) * (D[1].Y - D[0].Y) }; + const handleA = { X: newControl.X - dC.X, Y: newControl.Y - dC.Y }; + const handleB = { X: newControl.X + dD.X, Y: newControl.Y + dD.Y }; + return [handleA, handleB]; + } + + /** + * Deletes the current control point of the selected ink instance. + */ @undoBatch @action deletePoints = () => this.applyFunction((doc: Doc, ink: InkData) => { - var newPoints: { X: number, Y: number }[] = []; - const toRemove = Math.floor(((this._currPoint + 2) / 4)); - for (var i = 0; i < ink.length; i++) { + const newPoints: { X: number, Y: number }[] = []; + const toRemove = Math.floor(((this._currentPoint + 2) / 4)); + for (let i = 0; i < ink.length; i++) { if (Math.floor((i + 2) / 4) !== toRemove && (toRemove !== 0 || i > 3)) { newPoints.push({ X: ink[i].X, Y: ink[i].Y }); } } - this._currPoint = -1; + this._currentPoint = -1; if (newPoints.length < 4) return undefined; if (newPoints.length === 4) { const newerPoints: { X: number, Y: number }[] = []; @@ -166,12 +205,16 @@ export class InkStrokeProperties { return newerPoints; } return newPoints; - }, true); + }, true) + /** + * Rotates the entire selected ink instance. + * @param angle The angle at which to rotate the ink in radians. + */ @undoBatch @action - rotate = (angle: number) => { - this.applyFunction((doc: Doc, ink: InkData, ptsXscale: number, ptsYscale: number) => { + rotateInk = (angle: number) => { + this.applyFunction((doc: Doc, ink: InkData, xScale: number, yScale: number) => { const oldXrange = (xs => ({ coord: NumCast(doc.x), min: Math.min(...xs), max: Math.max(...xs) }))(ink.map(p => p.X)); const oldYrange = (ys => ({ coord: NumCast(doc.y), min: Math.min(...ys), max: Math.max(...ys) }))(ink.map(p => p.Y)); const centerPoint = { X: (oldXrange.min + oldXrange.max) / 2, Y: (oldYrange.min + oldYrange.max) / 2 }; @@ -186,42 +229,108 @@ export class InkStrokeProperties { }); } + /** + * Handles the movement/scaling of a control point. + */ @undoBatch @action - control = (xDiff: number, yDiff: number, controlNum: number) => - this.applyFunction((doc: Doc, ink: InkData, ptsXscale: number, ptsYscale: number) => { + moveControl = (deltaX: number, deltaY: number, controlIndex: number) => + this.applyFunction((doc: Doc, ink: InkData, xScale: number, yScale: number) => { const newPoints: { X: number, Y: number }[] = []; - const order = controlNum % 4; + const order = controlIndex % 4; for (var i = 0; i < ink.length; i++) { - newPoints.push( - (controlNum === i || - (order === 0 && i === controlNum + 1) || - (order === 0 && controlNum !== 0 && i === controlNum - 2) || - (order === 0 && controlNum !== 0 && i === controlNum - 1) || - (order === 3 && i === controlNum - 1) || - (order === 3 && controlNum !== ink.length - 1 && i === controlNum + 1) || - (order === 3 && controlNum !== ink.length - 1 && i === controlNum + 2) || - ((ink[0].X === ink[ink.length - 1].X) && (ink[0].Y === ink[ink.length - 1].Y) && (i === 0 || i === ink.length - 1) && (controlNum === 0 || controlNum === ink.length - 1)) - ) ? - { X: ink[i].X - xDiff / ptsXscale, Y: ink[i].Y - yDiff / ptsYscale } : - { X: ink[i].X, Y: ink[i].Y }); + const leftHandlePoint = order === 0 && i === controlIndex + 1; + const rightHandlePoint = order === 0 && controlIndex !== 0 && i === controlIndex - 2; + if (controlIndex === i || + leftHandlePoint || + rightHandlePoint || + (order === 0 && controlIndex !== 0 && i === controlIndex - 1) || + (order === 3 && i === controlIndex - 1) || + (order === 3 && controlIndex !== ink.length - 1 && i === controlIndex + 1) || + (order === 3 && controlIndex !== ink.length - 1 && i === controlIndex + 2) || + ((ink[0].X === ink[ink.length - 1].X) && (ink[0].Y === ink[ink.length - 1].Y) && (i === 0 || i === ink.length - 1) && (controlIndex === 0 || controlIndex === ink.length - 1))) { + newPoints.push({ X: ink[i].X - deltaX / xScale, Y: ink[i].Y - deltaY / yScale }); + } else { + newPoints.push({ X: ink[i].X, Y: ink[i].Y }); + } } return newPoints; + }) + + snapHandleTangent = (controlIndex: number, handleIndexA: number, handleIndexB: number) => { + this.applyFunction((doc: Doc, ink: InkData) => { + // doc.brokenIndices.splice(this._brokenIndices.indexOf(controlIndex), 1); + const [controlPoint, handleA, handleB] = [ink[controlIndex], ink[handleIndexA], ink[handleIndexB]]; + const oppositeHandleA = this.rotatePoint(handleA, controlPoint, Math.PI); + const angleDifference = this.angleChange(handleB, oppositeHandleA, controlPoint); + const newHandleB = this.rotatePoint(handleB, controlPoint, angleDifference); + ink[handleIndexB] = newHandleB; + return ink; }); + } - @undoBatch + /** + * Rotates the target point about the origin point for a given angle (radians). + */ @action - switchStk = (color: ColorState) => { - const val = String(color.hex); - this.colorStk = val; - return true; + rotatePoint = (target: PointData, origin: PointData, angle: number) => { + target.X -= origin.X; + target.Y -= origin.Y; + const newX = Math.cos(angle) * target.X - Math.sin(angle) * target.Y; + const newY = Math.sin(angle) * target.X + Math.cos(angle) * target.Y; + target.X = newX + origin.X; + target.Y = newY + origin.Y; + return target; + } + + /** + * Finds the angle (in radians) between two inputted vectors. + * + * α = arccos(a·b / |a|·|b|), where a and b are both vectors. + */ + angleBetweenTwoVectors = (vectorA: PointData, vectorB: PointData) => { + const magnitudeA = Math.sqrt(vectorA.X * vectorA.X + vectorA.Y * vectorA.Y); + const magnitudeB = Math.sqrt(vectorB.X * vectorB.X + vectorB.Y * vectorB.Y); + // Normalizing the vectors. + vectorA = { X: vectorA.X / magnitudeA, Y: vectorA.Y / magnitudeA }; + vectorB = { X: vectorB.X / magnitudeB, Y: vectorB.Y / magnitudeB }; + const dotProduct = vectorB.X * vectorA.X + vectorB.Y * vectorA.Y; + return Math.acos(dotProduct); } + /** + * Finds the angle difference (in radians) between two vectors relative to an arbitrary origin. + */ + angleChange = (a: PointData, b: PointData, origin: PointData) => { + // Finding vector representation of inputted points relative to new origin. + const vectorA = { X: a.X - origin.X, Y: a.Y - origin.Y }; + const vectorB = { X: b.X - origin.X, Y: b.Y - origin.Y }; + const crossProduct = vectorB.X * vectorA.Y - vectorB.Y * vectorA.X; + // Determining whether rotation is clockwise or counterclockwise. + const sign = crossProduct < 0 ? 1 : -1; + const theta = this.angleBetweenTwoVectors(vectorA, vectorB); + return sign * theta; + } + + /** + * Handles the movement/scaling of a handle point. + */ @undoBatch @action - switchFil = (color: ColorState) => { - const val = String(color.hex); - this.colorFil = val; - return true; - } + moveHandle = (deltaX: number, deltaY: number, handleIndex: number, oppositeHandleIndex: number, controlIndex: number) => + this.applyFunction((doc: Doc, ink: InkData, xScale: number, yScale: number) => { + const oldHandlePoint = ink[handleIndex]; + let oppositeHandlePoint = ink[oppositeHandleIndex]; + const controlPoint = ink[controlIndex]; + const newHandlePoint = { X: ink[handleIndex].X - deltaX / xScale, Y: ink[handleIndex].Y - deltaY / yScale }; + ink[handleIndex] = newHandlePoint; + const brokenIndices = Cast(doc.brokenInkIndices, listSpec("number")); + // Rotate opposite handle if user hasn't held 'Alt' key or not first/final control (which have only 1 handle). + if ((!brokenIndices || !brokenIndices?.includes(controlIndex)) && handleIndex !== 1 && handleIndex !== ink.length - 2) { + const angle = this.angleChange(oldHandlePoint, newHandlePoint, controlPoint); + oppositeHandlePoint = this.rotatePoint(oppositeHandlePoint, controlPoint, angle); + ink[oppositeHandleIndex] = oppositeHandlePoint; + } + return ink; + }) }
\ No newline at end of file diff --git a/src/client/views/InkingStroke.scss b/src/client/views/InkingStroke.scss deleted file mode 100644 index 30ab1967e..000000000 --- a/src/client/views/InkingStroke.scss +++ /dev/null @@ -1,11 +0,0 @@ -.inkingStroke { - mix-blend-mode: multiply; - stroke-linejoin: round; - stroke-linecap: round; - overflow: visible !important; - transform-origin: top left; - - svg:not(:root) { - overflow: visible !important; - } -}
\ No newline at end of file diff --git a/src/client/views/InkingStroke.tsx b/src/client/views/InkingStroke.tsx index 449019ca8..bd71aaf19 100644 --- a/src/client/views/InkingStroke.tsx +++ b/src/client/views/InkingStroke.tsx @@ -1,4 +1,5 @@ -import { action } from "mobx"; +import React = require("react"); +import { action, observable } from "mobx"; import { observer } from "mobx-react"; import { Doc } from "../../fields/Doc"; import { documentSchema } from "../../fields/documentSchemas"; @@ -10,180 +11,110 @@ import { setupMoveUpEvents, emptyFunction, returnFalse } from "../../Utils"; import { CognitiveServices } from "../cognitive_services/CognitiveServices"; import { InteractionUtils } from "../util/InteractionUtils"; import { Scripting } from "../util/Scripting"; -import { UndoManager } from "../util/UndoManager"; import { ContextMenu } from "./ContextMenu"; import { ViewBoxBaseComponent } from "./DocComponent"; -import "./InkingStroke.scss"; +import "./InkStroke.scss"; import { FieldView, FieldViewProps } from "./nodes/FieldView"; -import React = require("react"); import { InkStrokeProperties } from "./InkStrokeProperties"; import { CurrentUserUtils } from "../util/CurrentUserUtils"; +import { InkControls } from "./InkControls"; +import { InkHandles } from "./InkHandles"; type InkDocument = makeInterface<[typeof documentSchema]>; const InkDocument = makeInterface(documentSchema); @observer export class InkingStroke extends ViewBoxBaseComponent<FieldViewProps, InkDocument>(InkDocument) { - private _controlUndo?: UndoManager.Batch; + static readonly MaskDim = 50000; + @observable private _properties?: InkStrokeProperties; - public static LayoutString(fieldStr: string) { return FieldView.LayoutString(InkingStroke, fieldStr); } + constructor(props: FieldViewProps & InkDocument) { + super(props); - private analyzeStrokes = () => { + this._properties = InkStrokeProperties.Instance; + } + + public static LayoutString(fieldStr: string) { + return FieldView.LayoutString(InkingStroke, fieldStr); + } + + analyzeStrokes() { const data: InkData = Cast(this.dataDoc[this.fieldKey], InkField)?.inkData ?? []; CognitiveServices.Inking.Appliers.ConcatenateHandwriting(this.dataDoc, ["inkAnalysis", "handwriting"], [data]); } - public static toggleMask = action((inkDoc: Doc) => { + @action + public static toggleMask = (inkDoc: Doc) => { inkDoc.isInkMask = !inkDoc.isInkMask; inkDoc._backgroundColor = inkDoc.isInkMask ? "rgba(0,0,0,0.7)" : undefined; inkDoc.mixBlendMode = inkDoc.isInkMask ? "hard-light" : undefined; inkDoc.color = "#9b9b9bff"; inkDoc._stayInCollection = inkDoc.isInkMask ? true : undefined; - }); - - @action - onControlDown = (e: React.PointerEvent, controlNum: number): void => { - if (InkStrokeProperties.Instance) { - InkStrokeProperties.Instance.control(0, 0, 1); - const controlUndo = UndoManager.StartBatch("DocDecs set radius"); - const screenScale = this.props.ScreenToLocalTransform().Scale; - setupMoveUpEvents(this, e, - (e: PointerEvent, down: number[], delta: number[]) => { - InkStrokeProperties.Instance?.control(-delta[0] * screenScale, -delta[1] * screenScale, controlNum); - return false; - }, - () => controlUndo?.end(), emptyFunction); - } - } - - @action - changeCurrPoint = (i: number) => { - if (InkStrokeProperties.Instance) { - InkStrokeProperties.Instance._currPoint = i; - document.addEventListener("keydown", this.delPts, true); - } - } - - @action - delPts = (e: KeyboardEvent) => { - if (["-", "Backspace", "Delete"].includes(e.key)) { - if (InkStrokeProperties.Instance?.deletePoints()) e.stopPropagation(); - } } + /** + * Handles the movement of the entire ink object when the user clicks and drags. + */ onPointerDown = (e: React.PointerEvent) => { if (this.props.isSelected(true)) { - setupMoveUpEvents(this, e, returnFalse, emptyFunction, action((e: PointerEvent, doubleTap: boolean | undefined) => - doubleTap && InkStrokeProperties.Instance && (InkStrokeProperties.Instance._controlBtn = true))); + setupMoveUpEvents(this, e, returnFalse, emptyFunction, + action((e: PointerEvent, doubleTap: boolean | undefined) => + doubleTap && this._properties && (this._properties._controlButton = true)) + ); } } - public static MaskDim = 50000; render() { TraceMobx(); - const formatInstance = InkStrokeProperties.Instance; - if (!formatInstance) return (null); + // Extracting the ink data and formatting information of the current ink stroke. const data: InkData = Cast(this.dataDoc[this.fieldKey], InkField)?.inkData ?? []; - // const strokeWidth = Number(StrCast(this.layoutDoc.strokeWidth, ActiveInkWidth())); + const inkDoc: Doc = this.layoutDoc; const strokeWidth = Number(this.layoutDoc.strokeWidth); - const xs = data.map(p => p.X); - const ys = data.map(p => p.Y); - const lineTop = Math.min(...ys); - const lineBot = Math.max(...ys); - const lineLft = Math.min(...xs); - const lineRgt = Math.max(...xs); - const left = lineLft - strokeWidth / 2; + const lineTop = Math.min(...data.map(p => p.Y)); + const lineBottom = Math.max(...data.map(p => p.Y)); + const lineLeft = Math.min(...data.map(p => p.X)); + const lineRight = Math.max(...data.map(p => p.X)); + const left = lineLeft - strokeWidth / 2; const top = lineTop - strokeWidth / 2; - const right = lineRgt + strokeWidth / 2; - const bottom = lineBot + strokeWidth / 2; + const right = lineRight + strokeWidth / 2; + const bottom = lineBottom + strokeWidth / 2; const width = Math.max(1, right - left); const height = Math.max(1, bottom - top); const scaleX = width === strokeWidth ? 1 : (this.props.PanelWidth() - strokeWidth) / (width - strokeWidth); const scaleY = height === strokeWidth ? 1 : (this.props.PanelHeight() - strokeWidth) / (height - strokeWidth); const strokeColor = StrCast(this.layoutDoc.color, ""); + const dotsize = Math.max(width * scaleX, height * scaleY) / 40; - const points = InteractionUtils.CreatePolyline(data, left, top, strokeColor, strokeWidth, strokeWidth, + // Visually renders the polygonal line made by the user. + const inkLine = InteractionUtils.CreatePolyline(data, left, top, strokeColor, strokeWidth, strokeWidth, StrCast(this.layoutDoc.strokeBezier), StrCast(this.layoutDoc.fillColor, "none"), StrCast(this.layoutDoc.strokeStartMarker), StrCast(this.layoutDoc.strokeEndMarker), - StrCast(this.layoutDoc.strokeDash), scaleX, scaleY, "", "none", this.props.isSelected() && strokeWidth <= 5 && lineBot - lineTop > 1 && lineRgt - lineLft > 1, false); - - const hpoints = InteractionUtils.CreatePolyline(data, left, top, - this.props.isSelected() && strokeWidth > 5 ? strokeColor : "transparent", strokeWidth, (strokeWidth + 15), - StrCast(this.layoutDoc.strokeBezier), StrCast(this.layoutDoc.fillColor, "none"), - "none", "none", undefined, scaleX, scaleY, "", this.props.layerProvider?.(this.props.Document) === false ? "none" : "visiblepainted", false, true); - - //points for adding - const apoints = InteractionUtils.CreatePoints(data, left, top, strokeColor, strokeWidth, strokeWidth, + StrCast(this.layoutDoc.strokeDash), scaleX, scaleY, "", "none", + this.props.isSelected() && strokeWidth <= 5 && lineBottom - lineTop > 1 && lineRight - lineLeft > 1, + false); + // Thin blue line indicating that the current ink stroke is selected. + const selectedLine = InteractionUtils.CreatePolyline( + data, lineLeft - strokeWidth * 3, lineTop - strokeWidth * 3, "#1F85DE", strokeWidth / 6, + strokeWidth / 6, StrCast(this.layoutDoc.strokeBezier), StrCast(this.layoutDoc.fillColor, "none"), + StrCast(this.layoutDoc.strokeStartMarker), StrCast(this.layoutDoc.strokeEndMarker), + StrCast(this.layoutDoc.strokeDash), scaleX, scaleY, "", "none", + this.props.isSelected() && strokeWidth <= 5 && lineBottom - lineTop > 1 && lineRight - lineLeft > 1, + false); + // Invisible polygonal line that enables the ink to be selected by the user. + const clickableLine = InteractionUtils.CreatePolyline(data, left, top, + this.props.isSelected() && strokeWidth > 5 ? strokeColor : "transparent", strokeWidth, + strokeWidth + 15, StrCast(this.layoutDoc.strokeBezier), + StrCast(this.layoutDoc.fillColor, "none"), "none", "none", undefined, scaleX, scaleY, "", + this.props.layerProvider?.(this.props.Document) === false ? "none" : "visiblepainted", false, true); + // Set of points rendered upon the ink that can be added if a user clicks on one. + const addedPoints = InteractionUtils.CreatePoints(data, left, top, strokeColor, strokeWidth, strokeWidth, StrCast(this.layoutDoc.strokeBezier), StrCast(this.layoutDoc.fillColor, "none"), StrCast(this.layoutDoc.strokeStartMarker), StrCast(this.layoutDoc.strokeEndMarker), - StrCast(this.layoutDoc.strokeDash), scaleX, scaleY, "", "none", this.props.isSelected() && strokeWidth <= 5, false); - - const controlPoints: { X: number, Y: number, I: number }[] = []; - const handlePoints: { X: number, Y: number, I: number, dot1: number, dot2: number }[] = []; - const handleLine: { X1: number, Y1: number, X2: number, Y2: number, X3: number, Y3: number, dot1: number, dot2: number }[] = []; - if (data.length >= 4) { - for (var i = 0; i <= data.length - 4; i += 4) { - controlPoints.push({ X: data[i].X, Y: data[i].Y, I: i }); - controlPoints.push({ X: data[i + 3].X, Y: data[i + 3].Y, I: i + 3 }); - handlePoints.push({ X: data[i + 1].X, Y: data[i + 1].Y, I: i + 1, dot1: i, dot2: i === 0 ? i : i - 1 }); - handlePoints.push({ X: data[i + 2].X, Y: data[i + 2].Y, I: i + 2, dot1: i + 3, dot2: i === data.length ? i + 3 : i + 4 }); - } - - handleLine.push({ X1: data[0].X, Y1: data[0].Y, X2: data[0].X, Y2: data[0].Y, X3: data[1].X, Y3: data[1].Y, dot1: 0, dot2: 0 }); - for (var i = 2; i < data.length - 4; i += 4) { - - handleLine.push({ X1: data[i].X, Y1: data[i].Y, X2: data[i + 1].X, Y2: data[i + 1].Y, X3: data[i + 3].X, Y3: data[i + 3].Y, dot1: i + 1, dot2: i + 2 }); - - } - handleLine.push({ X1: data[data.length - 2].X, Y1: data[data.length - 2].Y, X2: data[data.length - 1].X, Y2: data[data.length - 1].Y, X3: data[data.length - 1].X, Y3: data[data.length - 1].Y, dot1: data.length - 1, dot2: data.length - 1 }); - - for (var i = 0; i <= data.length - 4; i += 4) { - handlePoints.push({ X: data[i + 1].X, Y: data[i + 1].Y, I: i + 1, dot1: i, dot2: i === 0 ? i : i - 1 }); - handlePoints.push({ X: data[i + 2].X, Y: data[i + 2].Y, I: i + 2, dot1: i + 3, dot2: i === data.length ? i + 3 : i + 4 }); - } - } - // if (data.length <= 4) { - // handlePoints = []; - // handleLine = []; - // controlPoints = []; - // for (var i = 0; i < data.length; i++) { - // controlPoints.push({ X: data[i].X, Y: data[i].Y, I: i }); - // } - - // } - const dotsize = Math.max(width * scaleX, height * scaleY) / 40; - - const addpoints = apoints.map((pts, i) => - <svg height="10" width="10" key={`add${i}`}> - <circle cx={(pts.X - left - strokeWidth / 2) * scaleX + strokeWidth / 2} cy={(pts.Y - top - strokeWidth / 2) * scaleY + strokeWidth / 2} r={strokeWidth / 2} stroke="invisible" strokeWidth={dotsize / 2} fill="invisible" - onPointerDown={(e) => { formatInstance.addPoints(pts.X, pts.Y, apoints, i, controlPoints); }} pointerEvents="all" cursor="all-scroll" - /> - </svg>); - const handles = handlePoints.map((pts, i) => - <svg height="10" width="10" key={`hdl${i}`}> - <circle cx={(pts.X - left - strokeWidth / 2) * scaleX + strokeWidth / 2} cy={(pts.Y - top - strokeWidth / 2) * scaleY + strokeWidth / 2} r={strokeWidth} strokeWidth={0} fill="green" - onPointerDown={(e) => this.onControlDown(e, pts.I)} pointerEvents="all" cursor="default" display={(pts.dot1 === formatInstance._currPoint || pts.dot2 === formatInstance._currPoint) ? "inherit" : "none"} /> - </svg>); - - const controls = controlPoints.map((pts, i) => - <svg height="10" width="10" key={`ctrl${i}`}> - <circle cx={(pts.X - left - strokeWidth / 2) * scaleX + strokeWidth / 2} cy={(pts.Y - top - strokeWidth / 2) * scaleY + strokeWidth / 2} r={strokeWidth / 2} strokeWidth={0} fill="red" - onPointerDown={(e) => { this.changeCurrPoint(pts.I); this.onControlDown(e, pts.I); }} pointerEvents="all" cursor="default" - /> - </svg>); - const handleLines = handleLine.map((pts, i) => - <svg height="100" width="100" key={`line${i}`} > - <line x1={(pts.X1 - left - strokeWidth / 2) * scaleX + strokeWidth / 2} y1={(pts.Y1 - top - strokeWidth / 2) * scaleY + strokeWidth / 2} - x2={(pts.X2 - left - strokeWidth / 2) * scaleX + strokeWidth / 2} y2={(pts.Y2 - top - strokeWidth / 2) * scaleY + strokeWidth / 2} stroke="green" strokeWidth={dotsize / 6} - display={(pts.dot1 === formatInstance._currPoint || pts.dot2 === formatInstance._currPoint) ? "inherit" : "none"} /> - <line x1={(pts.X2 - left - strokeWidth / 2) * scaleX + strokeWidth / 2} y1={(pts.Y2 - top - strokeWidth / 2) * scaleY + strokeWidth / 2} - x2={(pts.X3 - left - strokeWidth / 2) * scaleX + strokeWidth / 2} y2={(pts.Y3 - top - strokeWidth / 2) * scaleY + strokeWidth / 2} stroke="green" strokeWidth={dotsize / 6} - display={(pts.dot1 === formatInstance._currPoint || pts.dot2 === formatInstance._currPoint) ? "inherit" : "none"} /> - </svg>); - + StrCast(this.layoutDoc.strokeDash), scaleX, scaleY, "", "none", + this.props.isSelected() && strokeWidth <= 5, false); return ( - <svg className="inkingStroke" + <svg className="inkStroke" style={{ pointerEvents: this.props.Document.isInkMask && this.props.layerProvider?.(this.props.Document) !== false ? "all" : "none", transform: this.props.Document.isInkMask ? `translate(${InkingStroke.MaskDim / 2}px, ${InkingStroke.MaskDim / 2}px)` : undefined, @@ -196,19 +127,27 @@ export class InkingStroke extends ViewBoxBaseComponent<FieldViewProps, InkDocume if (cm) { !Doc.UserDoc().noviceMode && cm.addItem({ description: "Recognize Writing", event: this.analyzeStrokes, icon: "paint-brush" }); cm.addItem({ description: "Toggle Mask", event: () => InkingStroke.toggleMask(this.rootDoc), icon: "paint-brush" }); - cm.addItem({ description: "Edit Points", event: action(() => formatInstance._controlBtn = !formatInstance._controlBtn), icon: "paint-brush" }); - //cm.addItem({ description: "Format Shape...", event: this.formatShape, icon: "paint-brush" }); + cm.addItem({ description: "Edit Points", event: action(() => { if (this._properties) { this._properties._controlButton = !this._properties._controlButton; } }), icon: "paint-brush" }); } }} - ><defs> - </defs> - {hpoints} - {points} - {formatInstance._controlBtn && this.props.isSelected() ? addpoints : ""} - {formatInstance._controlBtn && this.props.isSelected() ? handleLines : ""} - {formatInstance._controlBtn && this.props.isSelected() ? handles : ""} - {formatInstance._controlBtn && this.props.isSelected() ? controls : ""} - + > + + {clickableLine} + {inkLine} + {this.props.isSelected() ? selectedLine : ""} + {this.props.isSelected() && this._properties?._controlButton ? + <> + <InkControls + data={data} + addedPoints={addedPoints} + format={[left, top, scaleX, scaleY, strokeWidth, dotsize]} + ScreenToLocalTransform={this.props.ScreenToLocalTransform} /> + <InkHandles + inkDoc={inkDoc} + data={data} + format={[left, top, scaleX, scaleY, strokeWidth, dotsize]} + ScreenToLocalTransform={this.props.ScreenToLocalTransform} /> + </> : ""} </svg> ); } diff --git a/src/client/views/Main.scss b/src/client/views/Main.scss index b1ad4868c..c8e64b5c4 100644 --- a/src/client/views/Main.scss +++ b/src/client/views/Main.scss @@ -1,4 +1,4 @@ -@import "globalCssVariables"; +@import "global/globalCssVariables"; @import "nodeModuleOverrides"; :root { @@ -54,7 +54,7 @@ button { background: black; outline: none; border: 0px; - color: $light-color; + color: $white; text-transform: uppercase; letter-spacing: 2px; font-size: 75%; @@ -63,7 +63,7 @@ button { } button:hover { - background: $main-accent; + background: $medium-gray; transform: scale(1.05); cursor: pointer; } diff --git a/src/client/views/MainView.scss b/src/client/views/MainView.scss index 3f04a0f3a..07ca0257c 100644 --- a/src/client/views/MainView.scss +++ b/src/client/views/MainView.scss @@ -1,4 +1,4 @@ -@import "globalCssVariables"; +@import "global/globalCssVariables"; @import "nodeModuleOverrides"; @@ -56,50 +56,50 @@ touch-action: none; .searchBox-container { - background: lightgray; + background: $light-gray; } } .mainView-container { - color: black; + color: $dark-gray; .lm_title { - background: #cacaca; - color: black; + background: $light-gray; + color: $dark-gray; } } .mainView-container-dark { - color: lightgray; + color: $light-gray; .lm_goldenlayout { - background: dimgray; + background: $medium-gray; } .lm_title { - background: black; + background: $dark-gray; color: unset; } .marquee { - border-color: white; + border-color: $white; } #search-input { - background: lightgray; + background: $light-gray; } .searchBox-container { - background: rgb(45, 45, 45); + background: $dark-gray; } .contextMenu-cont, .contextMenu-item { - background: dimGray; + background: $medium-gray; } .contextMenu-item:hover { - background: gray; + background: $medium-gray; } } @@ -113,7 +113,7 @@ .mainView-propertiesDragger { //background-color: rgb(140, 139, 139); - background-color: lightgrey; + background-color: $light-gray; height: 55px; width: 17px; position: absolute; @@ -163,10 +163,10 @@ flex-direction: column; position: relative; height: 100%; - background: dimgray; + background: $medium-gray; .documentView-node-topmost { - background: lightgrey; + background: $light-gray; } } @@ -174,32 +174,32 @@ right: 0; position: absolute; z-index: 2; - background-color: rgb(159, 159, 159); + background-color: $medium-gray; .editable-title { - background-color: lightgrey; + background-color: $light-gray; } } } .mainView-libraryHandle { - background-color: lightgrey; + background-color: $light-gray; } .mainView-innerContent-dark { .propertiesView { background-color: #252525; input { - background-color: dimgrey; + background-color: $medium-gray; } .propertiesView-sharingTable { - background-color: dimgrey; + background-color: $medium-gray; } .editable-title { - background-color: dimgrey; + background-color: $medium-gray; } .propertiesView-field { - background-color: dimgrey; + background-color: $medium-gray; } } .mainView-propertiesDragger, @@ -209,17 +209,17 @@ } .mainView-container-dark { .contextMenu-cont { - background: dimgrey; - color: white; + background: $medium-gray; + color: $white; input::placeholder { - color:white; + color:$white; } } } .mainView-menuPanel { min-width: var(--menuPanelWidth); - background-color: #121721; + background-color: $dark-gray; .collectionStackingView { scrollbar-width: none; @@ -233,13 +233,13 @@ padding: 7px; padding-left: 7px; width: 100%; - background: black; + background: $dark-gray; .mainView-menuPanel-button-wrap { width: 45px; /* padding: 5px; */ touch-action: none; - background: black; + background: $dark-gray; transform-origin: top left; /* margin-bottom: 5px; */ margin-top: 5px; @@ -247,7 +247,7 @@ border-radius: 8px; &:hover { - background: rgb(61, 61, 61); + background: $black; cursor: pointer; } } diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 4eeb1fc95..f34851b00 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -40,7 +40,7 @@ import { ContextMenu } from './ContextMenu'; import { DictationOverlay } from './DictationOverlay'; import { DocumentDecorations } from './DocumentDecorations'; import { GestureOverlay } from './GestureOverlay'; -import { MENU_PANEL_WIDTH, SEARCH_PANEL_HEIGHT } from './globalCssVariables.scss'; +import { MENU_PANEL_WIDTH, SEARCH_PANEL_HEIGHT } from './global/globalCssVariables.scss'; import { KeyManager } from './GlobalKeyHandler'; import { InkStrokeProperties } from './InkStrokeProperties'; import { LightboxView } from './LightboxView'; @@ -180,8 +180,8 @@ export class MainView extends React.Component { const targClass = targets[0].className.toString(); if (SearchBox.Instance._searchbarOpen || SearchBox.Instance.open) { const check = targets.some((thing) => - (thing.className === "collectionSchemaView-searchContainer" || (thing as any)?.dataset.icon === "filter" || - thing.className === "collectionSchema-header-menuOptions")); + (thing.className === "collectionSchemaView-searchContainer" || (thing as any)?.dataset.icon === "filter" || + thing.className === "collectionSchema-header-menuOptions")); !check && SearchBox.Instance.resetSearch(true); } !targClass.includes("contextMenu") && ContextMenu.Instance.closeMenu(); diff --git a/src/client/views/PropertiesButtons.scss b/src/client/views/PropertiesButtons.scss index 29d2bfcb7..484522bc7 100644 --- a/src/client/views/PropertiesButtons.scss +++ b/src/client/views/PropertiesButtons.scss @@ -1,4 +1,4 @@ -@import "globalCssVariables"; +@import "global/globalCssVariables"; $linkGap : 3px; @@ -7,13 +7,13 @@ $linkGap : 3px; } .propertiesButtons-linkButton-empty:hover { - background: $main-accent; + background: $medium-gray; transform: scale(1.05); cursor: pointer; } .propertiesButtons-linkButton-nonempty:hover { - background: $main-accent; + background: $medium-gray; transform: scale(1.05); cursor: pointer; } @@ -24,7 +24,7 @@ $linkGap : 3px; width: 29px; border-radius: 6px; pointer-events: auto; - background-color: #121721; + background-color: $dark-gray; color: #fcfbf7; text-transform: uppercase; letter-spacing: 2px; @@ -38,18 +38,18 @@ $linkGap : 3px; margin-left: 4px; &:hover { - background: $main-accent; + background: $medium-gray; transform: scale(1.05); cursor: pointer; } } .propertiesButtons-linkButton-empty.toggle-on { background-color: white; - color: black; + color: $dark-gray; } .propertiesButtons-linkButton-empty.toggle-hover { background-color: gray; - color: black; + color: $dark-gray; } .propertiesButtons-linkButton-empty.toggle-off { color: white; @@ -111,7 +111,7 @@ $linkGap : 3px; margin-left: 4px; &:hover { - background: $main-accent; + background: $medium-gray; transform: scale(1.05); cursor: pointer; } diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx index d09d949ff..4df3e4f00 100644 --- a/src/client/views/PropertiesView.tsx +++ b/src/client/views/PropertiesView.tsx @@ -86,7 +86,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { @observable openSlideOptions: boolean = false; @observable inOptions: boolean = false; - @observable _controlBtn: boolean = false; + @observable _controlButton: boolean = false; @observable _lock: boolean = false; componentDidMount() { @@ -540,7 +540,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> { const formatInstance = InkStrokeProperties.Instance; return !formatInstance ? (null) : <div className="inking-button"> <Tooltip title={<div className="dash-tooltip">{"Edit points"}</div>}> - <div className="inking-button-points" onPointerDown={action(() => formatInstance._controlBtn = !formatInstance._controlBtn)} style={{ backgroundColor: formatInstance._controlBtn ? "black" : "" }}> + <div className="inking-button-points" onPointerDown={action(() => formatInstance._controlButton = !formatInstance._controlButton)} style={{ backgroundColor: formatInstance._controlButton ? "black" : "" }}> <FontAwesomeIcon icon="bezier-curve" color="white" size="lg" /> </div> </Tooltip> diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx index 47a4a192c..55f6b8e3c 100644 --- a/src/client/views/StyleProvider.tsx +++ b/src/client/views/StyleProvider.tsx @@ -1,4 +1,5 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { Colors } from './global/globalEnums'; import { IconProp } from '@fortawesome/fontawesome-svg-core'; import 'golden-layout/src/css/goldenlayout-base.css'; import 'golden-layout/src/css/goldenlayout-dark-theme.css'; @@ -97,14 +98,14 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps case StyleProp.Color: const docColor: Opt<string> = StrCast(doc?.[fieldKey + "color"], StrCast(doc?._color)); if (docColor) return docColor; - const backColor = backgroundCol();// || (darkScheme() ? "black" : "white"); + const backColor = backgroundCol(); if (!backColor) return undefined; const nonAlphaColor = backColor.startsWith("#") ? (backColor as string).substring(0, 7) : backColor.startsWith("rgba") ? backColor.replace(/,.[^,]*\)/, ")").replace("rgba", "rgb") : backColor const col = Color(nonAlphaColor).rgb(); const colsum = (col.red() + col.green() + col.blue()); - if (colsum / col.alpha() > 400 || col.alpha() < 0.25) return "black"; - return "white"; + if (colsum / col.alpha() > 400 || col.alpha() < 0.25) return Colors.DARK_GRAY; + return Colors.WHITE; case StyleProp.Hidden: return BoolCast(doc?._hidden); case StyleProp.BorderRounding: return StrCast(doc?.[fieldKey + "borderRounding"]); case StyleProp.TitleHeight: return 15; @@ -114,30 +115,30 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps doc?.type === DocumentType.RTF) && showTitle() && !StrCast(doc?.showTitle).includes(":hover") ? 15 : 0; case StyleProp.BackgroundColor: { let docColor: Opt<string> = StrCast(doc?.[fieldKey + "backgroundColor"], StrCast(doc?._backgroundColor, isCaption ? "rgba(0,0,0,0.4)" : "")); - if (MainView.Instance.LastButton === doc) return darkScheme() ? "dimgrey" : "lightgrey"; + if (MainView.Instance.LastButton === doc) return darkScheme() ? Colors.MEDIUM_GRAY : Colors.LIGHT_GRAY; switch (doc?.type) { case DocumentType.PRESELEMENT: docColor = docColor || (darkScheme() ? "" : ""); break; - case DocumentType.PRES: docColor = docColor || (darkScheme() ? "#3e3e3e" : "white"); break; - case DocumentType.FONTICON: docColor = docColor || "black"; break; - case DocumentType.RTF: docColor = docColor || (darkScheme() ? "#2d2d2d" : "#f1efeb"); break; - case DocumentType.FILTER: docColor = docColor || (darkScheme() ? "#2d2d2d" : "rgba(105, 105, 105, 0.432)"); break; + case DocumentType.PRES: docColor = docColor || (darkScheme() ? Colors.DARK_GRAY : Colors.WHITE); break; + case DocumentType.FONTICON: docColor = docColor || Colors.DARK_GRAY; break; + case DocumentType.RTF: docColor = docColor || (darkScheme() ? Colors.DARK_GRAY : Colors.LIGHT_GRAY); break; + case DocumentType.FILTER: docColor = docColor || (darkScheme() ? Colors.DARK_GRAY : "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.LINKANCHOR: docColor = isAnchor ? "lightblue" : "transparent"; break; + case DocumentType.BUTTON: docColor = docColor || (darkScheme() ? Colors.DARK_GRAY : Colors.LIGHT_GRAY); break; + case DocumentType.LINKANCHOR: docColor = isAnchor ? Colors.LIGHT_BLUE : "transparent"; break; case DocumentType.LINK: docColor = (isAnchor ? docColor : "") || "transparent"; break; case DocumentType.IMG: case DocumentType.WEB: case DocumentType.PDF: case DocumentType.SCREENSHOT: - case DocumentType.VID: docColor = docColor || (darkScheme() ? "#2d2d2d" : "lightgray"); break; + case DocumentType.VID: docColor = docColor || (darkScheme() ? Colors.DARK_GRAY : Colors.LIGHT_GRAY); break; case DocumentType.COL: if (StrCast(Doc.LayoutField(doc)).includes("SliderBox")) break; - docColor = docColor ? docColor : + docColor = docColor ? Colors.DARK_GRAY : doc?._isGroup ? "#00000004" : // very faint highlight to show bounds of group - (Doc.IsSystem(doc) ? (darkScheme() ? "rgb(62,62,62)" : "lightgrey") : // system docs (seen in treeView) get a grayish background + (Doc.IsSystem(doc) ? (darkScheme() ? Colors.DARK_GRAY : Colors.LIGHT_GRAY) : // system docs (seen in treeView) get a grayish background isBackground() ? "cyan" : // ?? is there a good default for a background collection doc.annotationOn ? "#00000015" : // faint interior for collections on PDFs, images, etc StrCast((props?.renderDepth || 0) > 0 ? @@ -145,7 +146,7 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps Doc.UserDoc().activeCollectionBackground)); break; //if (doc._viewType !== CollectionViewType.Freeform && doc._viewType !== CollectionViewType.Time) return "rgb(62,62,62)"; - default: docColor = docColor || (darkScheme() ? "black" : "white"); break; + default: docColor = docColor || (darkScheme() ? Colors.DARK_GRAY : Colors.WHITE); break; } if (docColor && (!doc || props?.layerProvider?.(doc) === false)) docColor = Color(docColor.toLowerCase()).fade(0.5).toString(); return docColor; @@ -159,7 +160,7 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps case DocumentType.COL: return StrCast(doc?.boxShadow, isBackground() || doc?._isGroup || docProps?.LayoutTemplateString ? undefined : // groups have no drop shadow -- they're supposed to be "invisible". LayoutString's imply collection is being rendered as something else (e.g., title of a Slide) - `${darkScheme() ? "rgb(30, 32, 31) " : "#9c9396 "} ${StrCast(doc.boxShadow, "0.2vw 0.2vw 0.8vw")}`); + `${darkScheme() ? Colors.DARK_GRAY : Colors.MEDIUM_GRAY} ${StrCast(doc.boxShadow, "0.2vw 0.2vw 0.8vw")}`); case DocumentType.LABEL: if (doc?.annotationOn !== undefined) return "black 2px 2px 1px"; diff --git a/src/client/views/TemplateMenu.scss b/src/client/views/TemplateMenu.scss index bbed8cd96..f81cbdaab 100644 --- a/src/client/views/TemplateMenu.scss +++ b/src/client/views/TemplateMenu.scss @@ -1,4 +1,4 @@ -@import "globalCssVariables"; +@import "global/globalCssVariables"; .templating-menu { position: absolute; pointer-events: auto; @@ -24,7 +24,7 @@ cursor: pointer; &:hover { - background: $main-accent; + background: $medium-gray; transform: scale(1.05); } } @@ -32,7 +32,7 @@ .template-list { font-family: $sans-serif; font-size: 12px; - background-color: $light-color-secondary; + background-color: $light-gray; padding: 2px 12px; list-style: none; position: relative; diff --git a/src/client/views/_nodeModuleOverrides.scss b/src/client/views/_nodeModuleOverrides.scss index b8a7db034..56346b68b 100644 --- a/src/client/views/_nodeModuleOverrides.scss +++ b/src/client/views/_nodeModuleOverrides.scss @@ -2,7 +2,7 @@ // goldenlayout stuff div .lm_header { - background: $dark-color; + background: $dark-gray; } .lm_tab { diff --git a/src/client/views/animationtimeline/Keyframe.scss b/src/client/views/animationtimeline/Keyframe.scss index 84c8de287..38eb103c6 100644 --- a/src/client/views/animationtimeline/Keyframe.scss +++ b/src/client/views/animationtimeline/Keyframe.scss @@ -1,4 +1,4 @@ -@import "./../globalCssVariables.scss"; +@import "./../global/globalCssVariables.scss"; $timelineColor: #9acedf; @@ -15,11 +15,11 @@ $timelineDark: #77a1aa; height: 200px; top: 50%; position: relative; - background-color: $light-color; + background-color: $white; .menutable { tr:nth-child(odd) { - background-color: $light-color-secondary; + background-color: $light-gray; } } } @@ -67,7 +67,7 @@ $timelineDark: #77a1aa; height: 100%; position: absolute; pointer-events: none; - background: linear-gradient(to left, $timelineColor 10%, $light-color); + background: linear-gradient(to left, $timelineColor 10%, $white); } .fadeRight { @@ -75,7 +75,7 @@ $timelineDark: #77a1aa; height: 100%; position: absolute; pointer-events: none; - background: linear-gradient(to right, $timelineColor 10%, $light-color); + background: linear-gradient(to right, $timelineColor 10%, $white); } .divider { diff --git a/src/client/views/animationtimeline/Keyframe.tsx b/src/client/views/animationtimeline/Keyframe.tsx index e84022366..82b0218bf 100644 --- a/src/client/views/animationtimeline/Keyframe.tsx +++ b/src/client/views/animationtimeline/Keyframe.tsx @@ -1,7 +1,7 @@ import * as React from "react"; import "./Keyframe.scss"; import "./Timeline.scss"; -import "../globalCssVariables.scss"; +import "../global/globalCssVariables.scss"; import { observer } from "mobx-react"; import { observable, reaction, action, IReactionDisposer, observe, computed, runInAction, trace } from "mobx"; import { Doc, DocListCast, DocListCastAsync, Opt } from "../../../fields/Doc"; diff --git a/src/client/views/animationtimeline/Timeline.scss b/src/client/views/animationtimeline/Timeline.scss index f90249771..48422b789 100644 --- a/src/client/views/animationtimeline/Timeline.scss +++ b/src/client/views/animationtimeline/Timeline.scss @@ -1,4 +1,4 @@ -@import "./../globalCssVariables.scss"; +@import "./../global/globalCssVariables.scss"; $timelineColor: #9acedf; $timelineDark: #77a1aa; @@ -161,7 +161,7 @@ $timelineDark: #77a1aa; width: 100%; height: 300px; position: absolute; - background-color: $light-color-secondary; + background-color: $light-gray; border-bottom: 2px solid $timelineDark; transition: transform 500ms ease; @@ -251,7 +251,7 @@ $timelineDark: #77a1aa; top: 0px; width: 100px; height: 30%; - border: 1px solid $dark-color; + border: 1px solid $dark-gray; font-size: 12px; line-height: 11px; background-color: $timelineDark; diff --git a/src/client/views/animationtimeline/TimelineMenu.scss b/src/client/views/animationtimeline/TimelineMenu.scss index 7ee0a43d5..43a89419e 100644 --- a/src/client/views/animationtimeline/TimelineMenu.scss +++ b/src/client/views/animationtimeline/TimelineMenu.scss @@ -1,10 +1,10 @@ -@import "./../globalCssVariables.scss"; +@import "./../global/globalCssVariables.scss"; .timeline-menu-container{ position: absolute; display: flex; - box-shadow: $intermediate-color 0.2vw 0.2vw 0.4vw; + box-shadow: $medium-gray 0.2vw 0.2vw 0.4vw; flex-direction: column; background: whitesmoke; z-index: 10000; @@ -39,7 +39,7 @@ border-top-left-radius: 15px; border-top-right-radius: 15px; text-transform: uppercase; - background: $dark-color; + background: $dark-gray; letter-spacing: 2px; .timeline-menu-header-desc{ @@ -79,10 +79,10 @@ .timeline-menu-item:hover { border-width: .11px; border-style: none; - border-color: $intermediate-color; + border-color: $medium-gray; border-bottom-style: solid; border-top-style: solid; - background: $darker-alt-accent; + background: $medium-blue; } .timeline-menu-desc { diff --git a/src/client/views/animationtimeline/TimelineOverview.scss b/src/client/views/animationtimeline/TimelineOverview.scss index 283163ea7..c8d96c399 100644 --- a/src/client/views/animationtimeline/TimelineOverview.scss +++ b/src/client/views/animationtimeline/TimelineOverview.scss @@ -1,4 +1,4 @@ -@import "./../globalCssVariables.scss"; +@import "./../global/globalCssVariables.scss"; $timelineColor: #9acedf; $timelineDark: #77a1aa; diff --git a/src/client/views/animationtimeline/Track.scss b/src/client/views/animationtimeline/Track.scss index aec587a79..f45e0556d 100644 --- a/src/client/views/animationtimeline/Track.scss +++ b/src/client/views/animationtimeline/Track.scss @@ -1,4 +1,4 @@ -@import "./../globalCssVariables.scss"; +@import "./../global/globalCssVariables.scss"; .track-container { @@ -6,8 +6,8 @@ .inner { top: 0px; width: calc(100%); - background-color: $light-color; - border: 1px solid $dark-color; + background-color: $white; + border: 1px solid $dark-gray; position: relative; z-index: 100; } diff --git a/src/client/views/collections/CollectionDockingView.scss b/src/client/views/collections/CollectionDockingView.scss index f4736eb29..a054f0ae1 100644 --- a/src/client/views/collections/CollectionDockingView.scss +++ b/src/client/views/collections/CollectionDockingView.scss @@ -1,4 +1,4 @@ -@import "../../views/globalCssVariables.scss"; +@import "../../views/global/globalCssVariables.scss"; .lm_title { @@ -110,7 +110,7 @@ } .flexlayout__splitter { - background-color: black; + background-color: $dark-gray; } .flexlayout__splitter:hover { @@ -179,7 +179,7 @@ position: absolute; box-sizing: border-box; background-color: #222; - color: black; + color: $dark-gray; } .flexlayout__tab_button { @@ -268,7 +268,7 @@ } .flexlayout__tab_header_outer { - background-color: black; + background-color: $dark-gray; position: absolute; left: 0; right: 0; @@ -332,28 +332,28 @@ } .flexlayout__border_top { - background-color: black; + background-color: $dark-gray; border-bottom: 1px solid #ddd; box-sizing: border-box; overflow: hidden; } .flexlayout__border_bottom { - background-color: black; + background-color: $dark-gray; border-top: 1px solid #333; box-sizing: border-box; overflow: hidden; } .flexlayout__border_left { - background-color: black; + background-color: $dark-gray; border-right: 1px solid #333; box-sizing: border-box; overflow: hidden; } .flexlayout__border_right { - background-color: black; + background-color: $dark-gray; border-left: 1px solid #333; box-sizing: border-box; overflow: hidden; diff --git a/src/client/views/collections/CollectionLinearView.scss b/src/client/views/collections/CollectionLinearView.scss index ca72b98a5..ec8805907 100644 --- a/src/client/views/collections/CollectionLinearView.scss +++ b/src/client/views/collections/CollectionLinearView.scss @@ -1,4 +1,4 @@ -@import "../globalCssVariables"; +@import "../global/globalCssVariables"; @import "../_nodeModuleOverrides"; .collectionLinearView-outer { @@ -12,8 +12,8 @@ align-items: center; >span { - background: $dark-color; - color: $light-color; + background: $dark-gray; + color: $white; border-radius: 18px; margin-right: 6px; cursor: pointer; @@ -63,8 +63,8 @@ >label { margin-top: "auto"; margin-bottom: "auto"; - background: $dark-color; - color: $light-color; + background: $dark-gray; + color: $white; display: inline-block; border-radius: 18px; font-size: 12.5px; @@ -82,7 +82,7 @@ } label:hover { - background: $main-accent; + background: $medium-gray; transform: scale(1.15); } diff --git a/src/client/views/collections/CollectionMenu.scss b/src/client/views/collections/CollectionMenu.scss index dc5231a3a..c0fc774d3 100644 --- a/src/client/views/collections/CollectionMenu.scss +++ b/src/client/views/collections/CollectionMenu.scss @@ -1,5 +1,4 @@ -@import "../globalCssVariables"; - +@import "../global/globalCssVariables"; .collectionMenu-cont { position: relative; @@ -8,8 +7,8 @@ opacity: 0.9; z-index: 901; transition: top .5s; - background: #323232; - color: white; + background: $dark-gray; + color: $white; transform-origin: top left; top: 0; width: 100%; @@ -18,7 +17,7 @@ border-radius: 100%; width: 18px; height: 18px; - border: solid 1px #f5f5f5; + border: solid 1px $white; display: flex; align-items: center; justify-content: center; @@ -28,7 +27,7 @@ border-radius: 100%; width: 70%; height: 70%; - background: white; + background: $white; } .collectionMenu { @@ -43,7 +42,7 @@ margin-left: 3px; margin-right: 3px; width: 1.5px; - background-color: #656060; + background-color: $medium-gray; } .collectionViewBaseChrome { @@ -51,11 +50,11 @@ align-items: center; .collectionViewBaseChrome-viewPicker { - font-size: 75%; - outline-color: black; - color: white; + font-size: $small-text; + outline-color: $black; + color: $white; border: none; - background: #323232; + background: $dark-gray; } .collectionViewBaseChrome-viewPicker:focus { @@ -64,16 +63,16 @@ } .collectionViewBaseChrome-viewPicker:active { - outline-color: black; + outline-color: $black; } .collectionViewBaseChrome-button { - font-size: 75%; + font-size: $small-text; text-transform: uppercase; letter-spacing: 2px; - background: rgb(238, 238, 238); - color: purple; - outline-color: black; + background: $white; + color: $pink; + outline-color: $black; border: none; padding: 12px 10px 11px 10px; margin-left: 10px; @@ -82,11 +81,11 @@ .collectionViewBaseChrome-cmdPicker { margin-left: 3px; margin-right: 0px; - font-size: 75%; + font-size: $small-text; text-transform: capitalize; - color: white; + color: $white; border: none; - background: #323232; + background: $dark-gray; } .collectionViewBaseChrome-cmdPicker:focus { @@ -105,7 +104,7 @@ overflow: hidden; .commandEntry-drop { - color: white; + color: $white; width: 30px; margin-top: auto; margin-bottom: auto; @@ -113,11 +112,11 @@ } .commandEntry-outerDiv:hover{ - background-color: rgba(0,0,0,0.2); + background-color: $drop-shadow; .collectionViewBaseChrome-viewPicker, .collectionViewBaseChrome-cmdPicker{ - background: rgb(41,41,41); + background: $dark-gray; } } @@ -142,7 +141,7 @@ height: 100%; display: flex; background: transparent; - color: grey; + color: $medium-gray; justify-content: center; } @@ -150,31 +149,31 @@ margin-left: 5px; display: grid; border: none; - border-right: solid gray 1px; + border-right: solid $medium-gray 1px; .collectionViewBaseChrome-filterIcon { position: relative; display: flex; margin: auto; - background: #323232; - color: white; + background: $dark-gray; + color: $white; width: 30px; height: 30px; align-items: center; justify-content: center; border: none; - border-right: solid gray 1px; + border-right: solid $medium-gray 1px; } .collectionViewBaseChrome-viewSpecsInput { padding: 12px 10px 11px 10px; border: 0px; - color: grey; + color: $medium-gray; text-align: center; letter-spacing: 2px; - outline-color: black; - font-size: 75%; - background: rgb(238, 238, 238); + outline-color: $black; + font-size: $small-text; + background: $white; height: 100%; width: 75px; } @@ -187,8 +186,8 @@ z-index: 100; display: flex; flex-direction: column; - background: rgb(238, 238, 238); - box-shadow: grey 2px 2px 4px; + background: $white; + box-shadow: $medium-gray 2px 2px 4px; .qs-datepicker { left: unset; @@ -204,13 +203,13 @@ .collectionViewBaseChrome-viewSpecsMenu-rowLeft, .collectionViewBaseChrome-viewSpecsMenu-rowMiddle, .collectionViewBaseChrome-viewSpecsMenu-rowRight { - font-size: 75%; + font-size: $small-text; letter-spacing: 2px; - color: grey; + color: $medium-gray; margin-left: 10px; padding: 5px; border: none; - outline-color: black; + outline-color: $black; } } @@ -236,19 +235,19 @@ margin-left: 10; .collectionGridViewChrome-viewPicker { - font-size: 75%; + font-size: $small-text; //text-transform: uppercase; //letter-spacing: 2px; - background: #121721; - color: white; - outline-color: black; - color: white; + background: $dark-gray; + color: $white; + outline-color: $black; + color: $white; border: none; - border-right: solid gray 1px; + border-right: solid $medium-gray 1px; } .collectionGridViewChrome-viewPicker:active { - outline-color: black; + outline-color: $black; } .grid-control { @@ -268,11 +267,11 @@ .collectionGridViewChrome-entryBox { width: 50%; - color: black; + color: $black; } .collectionGridViewChrome-columnButton { - color: black; + color: $black; } } } @@ -302,7 +301,7 @@ align-items: center; display: flex; grid-auto-columns: auto; - font-size: 75%; + font-size: $small-text; letter-spacing: 2px; .collectionStackingViewChrome-pivotField-label, @@ -311,7 +310,7 @@ grid-column: 1; margin-right: 7px; user-select: none; - font-family: 'Roboto'; + font-family: $sans-serif; letter-spacing: normal; } @@ -329,13 +328,13 @@ } .collectionStackingViewChrome-sortIcon:hover { - background-color: rgba(0,0,0,0.2); + background-color: $drop-shadow; } .collectionStackingViewChrome-pivotField, .collectionTreeViewChrome-pivotField, .collection3DCarouselViewChrome-scrollSpeed { - color: white; + color: $white; grid-column: 2; grid-row: 1; width: 90%; @@ -344,7 +343,7 @@ height: 80%; border-radius: 7px; align-items: center; - background: #eeeeee; + background: $white; .editable-view-input, input, @@ -352,16 +351,16 @@ .editableView-container-editing { margin: auto; border: 0px; - color: grey !important; + color: $light-gray !important; text-align: center; letter-spacing: 2px; - outline-color: black; + outline-color: $black; height: 100%; } .react-autosuggest__container { margin: 0; - color: grey; + color: $medium-gray; padding: 0px; } } @@ -407,11 +406,11 @@ } .switchToText { - color: $main-accent; + color: $medium-gray; } .switchToText:hover { - color: $dark-color; + color: $dark-gray; } } @@ -424,11 +423,11 @@ .collectionMenu-urlInput { padding: 12px 10px 11px 10px; border: 0px; - color: black; - font-size: 10px; + color: $black; + font-size: $small-text; letter-spacing: 2px; - outline-color: black; - background: rgb(238, 238, 238); + outline-color: $black; + background: $white; width: 100%; min-width: 350px; margin-right: 10px; @@ -477,10 +476,10 @@ width: 20; height: 30; bottom: 0; - background: #323232; + background: $dark-gray; display: inline-flex; align-items: center; - color: white; + color: $white; } .backKeyframe { @@ -502,13 +501,13 @@ margin: auto; } - border-right: solid gray 1px; + border-right: solid $medium-gray 1px; } } .collectionSchemaViewChrome-cont { display: flex; - font-size: 10.5px; + font-size: $small-text; .collectionSchemaViewChrome-toggle { display: flex; @@ -527,19 +526,19 @@ .collectionSchemaViewChrome-toggler { width: 100px; height: 35px; - background-color: black; + background-color: $black; position: relative; } .collectionSchemaViewChrome-togglerButton { width: 47px; height: 30px; - background-color: $light-color-secondary; + background-color: $light-gray; // position: absolute; transition: all 0.5s ease; // top: 3px; margin-top: 3px; - color: gray; + color: $medium-gray; letter-spacing: 2px; text-transform: uppercase; display: flex; @@ -579,7 +578,7 @@ } .react-autosuggest__input { - border: 1px solid #aaa; + border: 1px solid $light-gray; border-radius: 4px; width: 100%; } @@ -603,11 +602,11 @@ overflow-y: auto; max-height: 400px; width: 180px; - border: 1px solid #aaa; - background-color: #fff; - font-family: Helvetica, sans-serif; + border: 1px solid $light-gray; + background-color: $white; + font-family: $sans-serif; font-weight: 300; - font-size: 16px; + font-size: $large-header; border-bottom-left-radius: 4px; border-bottom-right-radius: 4px; z-index: 2; @@ -625,5 +624,5 @@ } .react-autosuggest__suggestion--highlighted { - background-color: #ddd; + background-color: $light-gray; }
\ No newline at end of file diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index 8f2847139..e1e04915a 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -11,12 +11,13 @@ import { listSpec } from "../../../fields/Schema"; import { PastelSchemaPalette, SchemaHeaderField } from "../../../fields/SchemaHeaderField"; import { Cast, NumCast } from "../../../fields/Types"; import { TraceMobx } from "../../../fields/util"; -import { emptyFunction, emptyPath, returnFalse, setupMoveUpEvents, returnEmptyDoclist, returnTrue } from "../../../Utils"; +import { emptyFunction, returnEmptyDoclist, returnFalse, returnTrue, setupMoveUpEvents } from "../../../Utils"; +import { DocUtils } from "../../documents/Documents"; import { SelectionManager } from "../../util/SelectionManager"; import { SnappingManager } from "../../util/SnappingManager"; import { Transform } from "../../util/Transform"; import { undoBatch } from "../../util/UndoManager"; -import { COLLECTION_BORDER_WIDTH, SCHEMA_DIVIDER_WIDTH } from '../../views/globalCssVariables.scss'; +import { COLLECTION_BORDER_WIDTH, SCHEMA_DIVIDER_WIDTH } from '../../views/global/globalCssVariables.scss'; import { ContextMenu } from "../ContextMenu"; import { ContextMenuProps } from "../ContextMenuItem"; import '../DocumentDecorations.scss'; @@ -24,8 +25,7 @@ import { DocumentView } from "../nodes/DocumentView"; import { DefaultStyleProvider } from "../StyleProvider"; import "./CollectionSchemaView.scss"; import { CollectionSubView } from "./CollectionSubView"; -import { SchemaTable } from "./SchemaTable"; -import { DocUtils } from "../../documents/Documents"; +import { SchemaTable } from "../collections/collectionSchema/SchemaTable"; // bcz: need to add drag and drop of rows and columns. This seems like it might work for rows: https://codesandbox.io/s/l94mn1q657 export enum ColumnType { diff --git a/src/client/views/collections/CollectionStackingView.scss b/src/client/views/collections/CollectionStackingView.scss index 9f56a0c0e..4b123c8b6 100644 --- a/src/client/views/collections/CollectionStackingView.scss +++ b/src/client/views/collections/CollectionStackingView.scss @@ -1,4 +1,4 @@ -@import "../globalCssVariables"; +@import "../global/globalCssVariables"; .collectionMasonryView { display: inline; @@ -96,8 +96,8 @@ height: 2vw; width: 100%; font-family: $sans-serif; - background: $dark-color; - color: $light-color; + background: $dark-gray; + color: $white; } .collectionStackingView-columnDragger { @@ -128,7 +128,7 @@ margin-left: 2px; margin-right: 2px; margin-top: 2px; - background: $main-accent; + background: $medium-gray; height: 5px; &.active { @@ -180,11 +180,11 @@ .collectionStackingView-sectionHeader { text-align: center; margin: auto; - background: $main-accent; + background: $medium-gray; // overflow: hidden; overflow is visible so the color menu isn't hidden -ftong .editableView-input { - color: black; + color: $dark-gray; } .editableView-input:hover, @@ -205,7 +205,7 @@ display: flex; align-items: center; justify-content: center; - color: black; + color: $dark-gray; .editableView-container-editing-oneLine, .editableView-container-editing { diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx index 30f8e0112..7aa8dfd56 100644 --- a/src/client/views/collections/CollectionStackingView.tsx +++ b/src/client/views/collections/CollectionStackingView.tsx @@ -480,7 +480,7 @@ export class CollectionStackingView extends CollectionSubView<StackingDocument, if (value && this.columnHeaders) { const schemaHdrField = new SchemaHeaderField(value); this.columnHeaders.push(schemaHdrField); - DocUtils.addFieldEnumerations(undefined, this.pivotField, [{ title: value, _backgroundColor: schemaHdrField.color }]); + DocUtils.addFieldEnumerations(undefined, this.pivotField, [{ title: value, _backgroundColor: "schemaHdrField.color" }]); return true; } return false; diff --git a/src/client/views/collections/CollectionTreeView.scss b/src/client/views/collections/CollectionTreeView.scss index 72ab51784..ec461ab94 100644 --- a/src/client/views/collections/CollectionTreeView.scss +++ b/src/client/views/collections/CollectionTreeView.scss @@ -1,4 +1,4 @@ -@import "../globalCssVariables"; +@import "../global/globalCssVariables"; .collectionTreeView-dropTarget { border-width: $COLLECTION_BORDER_WIDTH; @@ -12,7 +12,7 @@ top: 0; padding-left: 10px; padding-right: 10px; - background: $light-color-secondary; + background: $light-gray; font-size: 13px; overflow: auto; user-select: none; @@ -40,7 +40,7 @@ } .delete-button { - color: $intermediate-color; + color: $medium-gray; // float: right; margin-left: 15px; // margin-top: 3px; @@ -71,7 +71,7 @@ .collectionTreeView-subtitle { font-style: italic; font-size: 8pt; - color: $intermediate-color; + color: $medium-gray; } .docContainer { diff --git a/src/client/views/collections/CollectionView.scss b/src/client/views/collections/CollectionView.scss index a5aef86de..5db489c0a 100644 --- a/src/client/views/collections/CollectionView.scss +++ b/src/client/views/collections/CollectionView.scss @@ -1,8 +1,8 @@ -@import "../globalCssVariables"; +@import "../global/globalCssVariables"; .collectionView { border-width: 0; - border-color: $light-color-secondary; + border-color: $light-gray; border-style: solid; border-radius: 0 0 $border-radius $border-radius; box-sizing: border-box; diff --git a/src/client/views/collections/TreeView.scss b/src/client/views/collections/TreeView.scss index 3f6fc8b0c..1ebc5873e 100644 --- a/src/client/views/collections/TreeView.scss +++ b/src/client/views/collections/TreeView.scss @@ -1,4 +1,4 @@ -@import "../globalCssVariables"; +@import "../global/globalCssVariables"; .treeView-label { max-height: 1.5em; @@ -14,7 +14,7 @@ .bullet-outline { position: relative; width: $TREE_BULLET_WIDTH; - color: $intermediate-color; + color: $medium-gray; transform: scale(0.5); display: inline-flex; align-items: center; @@ -45,7 +45,7 @@ .bullet { position: relative; width: $TREE_BULLET_WIDTH; - color: $intermediate-color; + color: $medium-gray; margin-top: 3px; transform: scale(1.3, 1.3); border: #80808030 1px solid; diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx index c1125c233..401bdcb02 100644 --- a/src/client/views/collections/TreeView.tsx +++ b/src/client/views/collections/TreeView.tsx @@ -20,7 +20,7 @@ import { SnappingManager } from '../../util/SnappingManager'; import { Transform } from '../../util/Transform'; import { undoBatch, UndoManager } from '../../util/UndoManager'; import { EditableView } from "../EditableView"; -import { TREE_BULLET_WIDTH } from '../globalCssVariables.scss'; +import { TREE_BULLET_WIDTH } from '../global/globalCssVariables.scss'; import { DocumentView, DocumentViewProps, StyleProviderFunc, DocumentViewInternal } from '../nodes/DocumentView'; import { FormattedTextBox } from '../nodes/formattedText/FormattedTextBox'; import { RichTextMenu } from '../nodes/formattedText/RichTextMenu'; diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormRemoteCursors.scss b/src/client/views/collections/collectionFreeForm/CollectionFreeFormRemoteCursors.scss index c5b8fc5e8..5fa01b102 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormRemoteCursors.scss +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormRemoteCursors.scss @@ -1,4 +1,4 @@ -@import "globalCssVariables"; +@import "global/globalCssVariables"; .collectionFreeFormRemoteCursors-cont { diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss index eb0538c41..79e063f7f 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss @@ -1,4 +1,4 @@ -@import "../../globalCssVariables"; +@import "../../global/globalCssVariables"; .collectionfreeformview-none { position: inherit; @@ -226,7 +226,7 @@ // linear-gradient(to bottom, $light-color-secondary 1px, transparent 1px); // background-size: 30px 30px; // } - border: 0px solid $light-color-secondary; + border: 0px solid $light-gray; border-radius: inherit; box-sizing: border-box; position: absolute; diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index accb80c5a..a4e310e6c 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -28,7 +28,7 @@ import { SelectionManager } from "../../../util/SelectionManager"; import { SnappingManager } from "../../../util/SnappingManager"; import { Transform } from "../../../util/Transform"; import { undoBatch } from "../../../util/UndoManager"; -import { COLLECTION_BORDER_WIDTH } from "../../../views/globalCssVariables.scss"; +import { COLLECTION_BORDER_WIDTH } from "../../../views/global/globalCssVariables.scss"; import { Timeline } from "../../animationtimeline/Timeline"; import { ContextMenu } from "../../ContextMenu"; import { DocumentDecorations } from "../../DocumentDecorations"; @@ -834,10 +834,10 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P map(doc => ({ ...this.childDataProvider(doc, ""), ...this.childSizeProvider(doc, "") })); if (measuredDocs.length) { const ranges = measuredDocs.reduce(({ xrange, yrange }, { x, y, width, height }) => // computes range of content - ({ - xrange: { min: Math.min(xrange.min, x), max: Math.max(xrange.max, x + width) }, - yrange: { min: Math.min(yrange.min, y), max: Math.max(yrange.max, y + height) } - }) + ({ + xrange: { min: Math.min(xrange.min, x), max: Math.max(xrange.max, x + width) }, + yrange: { min: Math.min(yrange.min, y), max: Math.max(yrange.max, y + height) } + }) , { xrange: { min: Number.MAX_VALUE, max: -Number.MAX_VALUE }, yrange: { min: Number.MAX_VALUE, max: -Number.MAX_VALUE } diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaCells.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaCells.tsx index f75179cea..90f64f163 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaCells.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaCells.tsx @@ -26,7 +26,7 @@ import { SnappingManager } from "../../../util/SnappingManager"; import { undoBatch } from "../../../util/UndoManager"; import '../../../views/DocumentDecorations.scss'; import { EditableView } from "../../EditableView"; -import { MAX_ROW_HEIGHT } from '../../globalCssVariables.scss'; +import { MAX_ROW_HEIGHT } from '../../global/globalCssVariables.scss'; import { DocumentIconContainer } from "../../nodes/DocumentIcon"; import { OverlayView } from "../../OverlayView"; import "./CollectionSchemaView.scss"; diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.scss b/src/client/views/collections/collectionSchema/CollectionSchemaView.scss index b57fee0e4..40cdcd14b 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.scss +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.scss @@ -1,7 +1,7 @@ -@import "../../globalCssVariables"; +@import "../../global/globalCssVariables.scss"; .collectionSchemaView-container { border-width: $COLLECTION_BORDER_WIDTH; - border-color: $intermediate-color; + border-color: $medium-gray; border-style: solid; border-radius: $border-radius; box-sizing: border-box; @@ -33,13 +33,13 @@ cursor: col-resize; } // .documentView-node:first-child { - // background: $light-color; + // background: $white; // } } .collectionSchemaView-searchContainer { border-width: $COLLECTION_BORDER_WIDTH; - border-color: $intermediate-color; + border-color: $medium-gray; border-style: solid; border-radius: $border-radius; box-sizing: border-box; @@ -72,7 +72,7 @@ cursor: col-resize; } // .documentView-node:first-child { - // background: $light-color; + // background: $white; // } } @@ -245,7 +245,7 @@ button.add-column { } } label { - color: $main-accent; + color: $medium-gray; font-weight: normal; letter-spacing: 2px; text-transform: uppercase; @@ -260,11 +260,11 @@ button.add-column { background-color: white; transition: background-color 0.2s; &:hover { - background-color: $light-color-secondary; + background-color: $light-gray; } &.active { font-weight: bold; - border: 2px solid $light-color-secondary; + border: 2px solid $light-gray; } svg { color: gray; @@ -277,7 +277,7 @@ button.add-column { //width: 100%; background-color: white; input { - border: 2px solid $light-color-secondary; + border: 2px solid $light-gray; padding: 3px; height: 28px; font-weight: bold; @@ -303,7 +303,7 @@ button.add-column { border-top: 0; } &:hover { - background-color: $light-color-secondary; + background-color: $light-gray; } } } @@ -329,7 +329,7 @@ button.add-column { height: 100%; background-color: white; &.row-focused .rt-td { - background-color: #bfffc0; //$light-color-secondary; + background-color: #bfffc0; //$light-gray; } &.row-wrapped { .rt-td { diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx index ef28f75c8..585cda729 100644 --- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx +++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx @@ -11,21 +11,21 @@ import { listSpec } from "../../../../fields/Schema"; import { PastelSchemaPalette, SchemaHeaderField } from "../../../../fields/SchemaHeaderField"; import { Cast, NumCast } from "../../../../fields/Types"; import { TraceMobx } from "../../../../fields/util"; -import { emptyFunction, emptyPath, returnFalse, setupMoveUpEvents, returnEmptyDoclist, returnTrue } from "../../../../Utils"; +import { emptyFunction, returnEmptyDoclist, returnFalse, returnTrue, setupMoveUpEvents } from "../../../../Utils"; +import { DocUtils } from "../../../documents/Documents"; import { SelectionManager } from "../../../util/SelectionManager"; import { SnappingManager } from "../../../util/SnappingManager"; import { Transform } from "../../../util/Transform"; import { undoBatch } from "../../../util/UndoManager"; -import { COLLECTION_BORDER_WIDTH, SCHEMA_DIVIDER_WIDTH } from '../../globalCssVariables.scss'; +import '../../../views/DocumentDecorations.scss'; import { ContextMenu } from "../../ContextMenu"; import { ContextMenuProps } from "../../ContextMenuItem"; -import '../../../views/DocumentDecorations.scss'; +import { COLLECTION_BORDER_WIDTH, SCHEMA_DIVIDER_WIDTH } from '../../global/globalCssVariables.scss'; import { DocumentView } from "../../nodes/DocumentView"; import { DefaultStyleProvider } from "../../StyleProvider"; -import "./CollectionSchemaView.scss"; import { CollectionSubView } from "../CollectionSubView"; +import "./CollectionSchemaView.scss"; import { SchemaTable } from "./SchemaTable"; -import { DocUtils } from "../../../documents/Documents"; // bcz: need to add drag and drop of rows and columns. This seems like it might work for rows: https://codesandbox.io/s/l94mn1q657 export enum ColumnType { diff --git a/src/client/views/collections/collectionSchema/SchemaTable.tsx b/src/client/views/collections/collectionSchema/SchemaTable.tsx index 0d5c9e077..de08c327a 100644 --- a/src/client/views/collections/collectionSchema/SchemaTable.tsx +++ b/src/client/views/collections/collectionSchema/SchemaTable.tsx @@ -21,7 +21,7 @@ import { DocumentType } from "../../../documents/DocumentTypes"; import { CompileScript, Transformer, ts } from "../../../util/Scripting"; import { Transform } from "../../../util/Transform"; import { undoBatch } from "../../../util/UndoManager"; -import { COLLECTION_BORDER_WIDTH, SCHEMA_DIVIDER_WIDTH } from '../../globalCssVariables.scss'; +import { COLLECTION_BORDER_WIDTH, SCHEMA_DIVIDER_WIDTH } from '../../global/globalCssVariables.scss'; import { ContextMenu } from "../../ContextMenu"; import '../../../views/DocumentDecorations.scss'; import { DocumentView } from "../../nodes/DocumentView"; diff --git a/src/client/views/globalCssVariables.scss b/src/client/views/global/globalCssVariables.scss index ccc9306c4..ead5e166e 100644 --- a/src/client/views/globalCssVariables.scss +++ b/src/client/views/global/globalCssVariables.scss @@ -1,28 +1,37 @@ @import url("https://fonts.googleapis.com/css?family=Noto+Sans:400,700|Crimson+Text:400,400i,700"); // colors -$light-color: #fcfbf7; -$light-color-secondary:#f1efeb; -//$main-accent: #61aaa3; -$main-accent: #aaaaa3; -// $alt-accent: #cdd5ec; -// $alt-accent: #cdeceb; -//$alt-accent: #59dff7; -$alt-accent: #c2c2c5; -$lighter-alt-accent: rgb(207, 220, 240); -$darker-alt-accent: #b2cef8; -$intermediate-color: #9c9396; -$dark-color: #121721; -$link-color: #add8e6; -$antimodemenu-height: 35px; +$white: #ffffff; +$light-gray:#dfdfdf; +$medium-gray: #9F9F9F; +$dark-gray: #323232; +$black: #000000; + +$light-blue: #BDDDF5; +$medium-blue: #4476F7; +$pink: #E0217D; +$yellow: #F5D747; + +$drop-shadow: "#32323215"; + +//padding +$minimum-padding: 4px; +$medium-padding: 16px; +$large-padding: 32px; + +//icon sizes +$icon-size: 28px; + +$antimodemenu-height: 36px; + // fonts -$sans-serif: "Noto Sans", -sans-serif; +$sans-serif: "Noto Sans", sans-serif; +$large-header: 16px; +$body-text: 12px; +$small-text: 9px; // $sans-serif: "Roboto Slab", sans-serif; -$serif: "Crimson Text", -serif; + // misc values $border-radius: 0.3em; -// $search-thumnail-size: 130; // dragged items @@ -35,7 +44,7 @@ $docDecorations-zindex: 998; // then doc decorations appear over everything else $remoteCursors-zindex: 997; // ... not sure what level the remote cursors should go -- is this right? $COLLECTION_BORDER_WIDTH: 0; $SCHEMA_DIVIDER_WIDTH: 4; -$MINIMIZED_ICON_SIZE:25; +$MINIMIZED_ICON_SIZE:24; $MAX_ROW_HEIGHT: 44px; $DFLT_IMAGE_NATIVE_DIM: 900px; $MENU_PANEL_WIDTH: 60px; diff --git a/src/client/views/globalCssVariables.scss.d.ts b/src/client/views/global/globalCssVariables.scss.d.ts index 11e62e1eb..11e62e1eb 100644 --- a/src/client/views/globalCssVariables.scss.d.ts +++ b/src/client/views/global/globalCssVariables.scss.d.ts diff --git a/src/client/views/global/globalEnums.tsx b/src/client/views/global/globalEnums.tsx new file mode 100644 index 000000000..1e0381c33 --- /dev/null +++ b/src/client/views/global/globalEnums.tsx @@ -0,0 +1,34 @@ +export enum Colors { + BLACK = "#000000", + DARK_GRAY = "#323232", + MEDIUM_GRAY = "#9F9F9F", + LIGHT_GRAY = "#DFDFDF", + WHITE = "#FFFFFF", + MEDIUM_BLUE = "#4476F7", + LIGHT_BLUE = "#BDDDF5", + PINK = "#E0217D", + YELLOW = "#F5D747", + DROP_SHADOW = "#32323215", +} + +export enum FontSizes { + //Bolded + LARGE_HEADER = "16px", + + //Bolded or unbolded + BODY_TEXT = "12px", + + //Bolded + SMALL_TEXT = "9px", +} + +export enum Padding { + MINIMUM_PADDING = "4px", + SMALL_PADDING = "8px", + MEDIUM_PADDING = "16px", + LARGE_PADDING = "32px", +} + +export enum IconSizes { + ICON_SIZE = "28px", +}
\ No newline at end of file diff --git a/src/client/views/linking/LinkEditor.scss b/src/client/views/linking/LinkEditor.scss index 7e6999cdc..839ebf894 100644 --- a/src/client/views/linking/LinkEditor.scss +++ b/src/client/views/linking/LinkEditor.scss @@ -1,4 +1,4 @@ -@import "../globalCssVariables"; +@import "../global/globalCssVariables"; .linkEditor { width: 100%; @@ -20,7 +20,7 @@ } .linkEditor-info { - //border-bottom: 0.5px solid $light-color-secondary; + //border-bottom: 0.5px solid $light-gray; //padding-bottom: 1px; padding-top: 5px; padding-left: 5px; @@ -195,7 +195,7 @@ } .linkEditor-group { - background-color: $light-color-secondary; + background-color: $light-gray; padding: 6px; margin: 3px 0; border-radius: 3px; @@ -254,8 +254,8 @@ } .linkEditor-option { - background-color: $light-color-secondary; - border: 1px solid $intermediate-color; + background-color: $light-gray; + border: 1px solid $medium-gray; border-top: 0; padding: 3px; cursor: pointer; @@ -272,7 +272,7 @@ .linkEditor-typeButton { background-color: transparent; - color: $dark-color; + color: $dark-gray; height: 20px; padding: 0 3px; padding-bottom: 2px; @@ -285,7 +285,7 @@ width: calc(100% - 40px); &:hover { - background-color: $light-color; + background-color: $white; } } diff --git a/src/client/views/linking/LinkMenu.scss b/src/client/views/linking/LinkMenu.scss index a90bf8b0a..a2ea42999 100644 --- a/src/client/views/linking/LinkMenu.scss +++ b/src/client/views/linking/LinkMenu.scss @@ -1,4 +1,4 @@ -@import "../globalCssVariables"; +@import "../global/globalCssVariables"; .linkMenu { width: auto; diff --git a/src/client/views/linking/LinkMenuItem.scss b/src/client/views/linking/LinkMenuItem.scss index 4e13ef8c8..4f9881565 100644 --- a/src/client/views/linking/LinkMenuItem.scss +++ b/src/client/views/linking/LinkMenuItem.scss @@ -1,7 +1,7 @@ -@import "../globalCssVariables"; +@import "../global/globalCssVariables"; .linkMenu-item { - // border-top: 0.5px solid $main-accent; + // border-top: 0.5px solid $medium-gray; position: relative; display: flex; border-bottom: 0.5px solid black; @@ -102,7 +102,7 @@ .link-metadata { padding: 0 10px 0 16px; margin-bottom: 4px; - color: $main-accent; + color: $medium-gray; font-style: italic; font-size: 10.5px; } @@ -143,8 +143,8 @@ padding-right: 6px; border-radius: 50%; pointer-events: auto; - background-color: $dark-color; - color: $light-color; + background-color: $dark-gray; + color: $white; font-size: 65%; transition: transform 0.2s; text-align: center; @@ -162,7 +162,7 @@ } &:hover { - background: $main-accent; + background: $medium-gray; cursor: pointer; } } diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx index a0a40becb..9b75cd8f9 100644 --- a/src/client/views/nodes/DocumentContentsView.tsx +++ b/src/client/views/nodes/DocumentContentsView.tsx @@ -64,6 +64,7 @@ interface HTMLtagProps { htmltag: string; onClick?: ScriptField; onInput?: ScriptField; + scaling: number; } //"<HTMLdiv borderRadius='100px' onClick={this.bannerColor=this.bannerColor==='red'?'green':'red'} overflow='hidden' position='absolute' width='100%' height='100%' transform='rotate({2*this.x+this.y}deg)'> <ImageBox {...props} fieldKey={'data'}/> <HTMLspan width='200px' top='0' height='35px' textAlign='center' paddingTop='10px' transform='translate(-40px, 45px) rotate(-45deg)' position='absolute' color='{this.bannerColor===`green`?`light`:`dark`}blue' backgroundColor='{this.bannerColor===`green`?`dark`:`light`}blue'> {this.title}</HTMLspan></HTMLdiv>" @@ -82,7 +83,7 @@ interface HTMLtagProps { export class HTMLtag extends React.Component<HTMLtagProps> { click = (e: React.MouseEvent) => { const clickScript = (this.props as any).onClick as Opt<ScriptField>; - clickScript?.script.run({ this: this.props.Document, self: this.props.RootDoc }); + clickScript?.script.run({ this: this.props.Document, self: this.props.RootDoc, scale: this.props.scaling }); } onInput = (e: React.FormEvent<HTMLDivElement>) => { const onInputScript = (this.props as any).onInput as Opt<ScriptField>; @@ -90,9 +91,9 @@ export class HTMLtag extends React.Component<HTMLtagProps> { } render() { const style: { [key: string]: any } = {}; - const divKeys = OmitKeys(this.props, ["children", "htmltag", "RootDoc", "Document", "key", "onInput", "onClick", "__proto__"]).omit; + const divKeys = OmitKeys(this.props, ["children", "htmltag", "RootDoc", "scaling", "Document", "key", "onInput", "onClick", "__proto__"]).omit; const replacer = (match: any, expr: string, offset: any, string: any) => { // bcz: this executes a script to convert a propery expression string: { script } into a value - return ScriptField.MakeFunction(expr, { self: Doc.name, this: Doc.name })?.script.run({ self: this.props.RootDoc, this: this.props.Document }).result as string || ""; + return ScriptField.MakeFunction(expr, { self: Doc.name, this: Doc.name, scale: "number" })?.script.run({ self: this.props.RootDoc, this: this.props.Document, scale: this.props.scaling }).result as string || ""; }; Object.keys(divKeys).map((prop: string) => { const p = (this.props as any)[prop] as string; @@ -184,7 +185,7 @@ export class DocumentContentsView extends React.Component<DocumentViewProps & Fo // replace HTML<tag> with corresponding HTML tag as in: <HTMLdiv> becomes <HTMLtag Document={props.Document} htmltag='div'> const replacer2 = (match: any, p1: string, offset: any, string: any) => { - return `<HTMLtag RootDoc={props.RootDoc} Document={props.Document} htmltag='${p1}'`; + return `<HTMLtag RootDoc={props.RootDoc} Document={props.Document} scaling='${this.props.scaling?.() || 1}' htmltag='${p1}'`; }; layoutFrame = layoutFrame.replace(/<HTML([a-zA-Z0-9_-]+)/g, replacer2); @@ -200,7 +201,7 @@ export class DocumentContentsView extends React.Component<DocumentViewProps & Fo if (splits.length > 1) { const code = XRegExp.matchRecursive(splits[1], "{", "}", "", { valueNames: ["between", "left", "match", "right", "between"] }); layoutFrame = splits[0] + ` ${func}={props.${func}} ` + splits[1].substring(code[1].end + 1); - return ScriptField.MakeScript(code[1].value, { this: Doc.name, self: Doc.name, value: "string" }); + return ScriptField.MakeScript(code[1].value, { this: Doc.name, self: Doc.name, scale: "number", value: "string" }); } return undefined; // add input function to props diff --git a/src/client/views/nodes/DocumentLinksButton.scss b/src/client/views/nodes/DocumentLinksButton.scss index 735aa669f..daffaf9e7 100644 --- a/src/client/views/nodes/DocumentLinksButton.scss +++ b/src/client/views/nodes/DocumentLinksButton.scss @@ -1,4 +1,4 @@ -@import "../globalCssVariables.scss"; +@import "../global/globalCssVariables.scss"; .documentLinksButton-cont { @@ -37,7 +37,7 @@ font-weight: bold; &:hover { - background: $main-accent; + background: $medium-gray; transform: scale(1.05); cursor: pointer; } diff --git a/src/client/views/nodes/DocumentView.scss b/src/client/views/nodes/DocumentView.scss index bdbece621..8f86417d6 100644 --- a/src/client/views/nodes/DocumentView.scss +++ b/src/client/views/nodes/DocumentView.scss @@ -1,4 +1,4 @@ -@import "../globalCssVariables"; +@import "../global/globalCssVariables"; .documentView-effectsWrapper { border-radius: inherit; @@ -22,7 +22,7 @@ transition: outline .3s linear; cursor: grab; - // background: $light-color; //overflow: hidden; + // background: $white; //overflow: hidden; transform-origin: left top; &.minimized { @@ -218,6 +218,6 @@ .documentView-node:first-child { position: relative; - background: "#B59B66"; //$light-color; + background: "#B59B66"; //$white; } }
\ No newline at end of file diff --git a/src/client/views/nodes/FontIconBox.scss b/src/client/views/nodes/FontIconBox.scss index 33ac85a0e..718af2c16 100644 --- a/src/client/views/nodes/FontIconBox.scss +++ b/src/client/views/nodes/FontIconBox.scss @@ -1,5 +1,7 @@ +@import "../global/globalCssVariables"; + .fontIconBox-label { - color: white; + color: $white; margin-right: 4px; margin-top: 1px; position: relative; @@ -22,8 +24,8 @@ position: absolute; top: -10px; right: -10px; - color: white; - background: #f44b42; + color: $white; + background: $pink; font-weight: 300; border-radius: 100%; width: 25px; @@ -37,7 +39,7 @@ .menuButton-circle, .menuButton-round { border-radius: 100%; - background-color: black; + background-color: $dark-gray; padding: 0; .fontIconBox-label { @@ -47,13 +49,14 @@ } &:hover { - background-color: #aaaaa3; + background-color: $light-gray; } } .menuButton-square { padding-top: 3px; padding-bottom: 3px; + background-color: $dark-gray; .fontIconBox-label { border-radius: 0px; diff --git a/src/client/views/nodes/KeyValueBox.scss b/src/client/views/nodes/KeyValueBox.scss index eb7c2f32b..ffcba4981 100644 --- a/src/client/views/nodes/KeyValueBox.scss +++ b/src/client/views/nodes/KeyValueBox.scss @@ -1,10 +1,10 @@ -@import "../globalCssVariables"; +@import "../global/globalCssVariables"; .keyValueBox-cont { overflow-y: scroll; width:100%; height: 100%; - background-color: $light-color; - border: 1px solid $intermediate-color; + background-color: $white; + border: 1px solid $medium-gray; border-radius: $border-radius; box-sizing: border-box; display: inline-block; @@ -56,8 +56,8 @@ $header-height: 30px; width:100%; position: relative; display: inline-block; - background: $intermediate-color; - color: $light-color; + background: $medium-gray; + color: $white; text-transform: uppercase; letter-spacing: 2px; font-size: 12px; @@ -66,7 +66,7 @@ $header-height: 30px; th { font-weight: normal; &:first-child { - border-right: 1px solid $light-color; + border-right: 1px solid $white; } } } @@ -76,9 +76,9 @@ $header-height: 30px; display: flex; width:100%; height:$header-height; - background: $light-color; + background: $white; .formattedTextBox-cont { - background: $light-color; + background: $white; } } .keyValueBox-cont { @@ -116,8 +116,8 @@ $header-height: 30px; display: flex; width:100%; height:30px; - background: $light-color-secondary; + background: $light-gray; .formattedTextBox-cont { - background: $light-color-secondary; + background: $light-gray; } }
\ No newline at end of file diff --git a/src/client/views/nodes/KeyValuePair.scss b/src/client/views/nodes/KeyValuePair.scss index f78767234..5b660e582 100644 --- a/src/client/views/nodes/KeyValuePair.scss +++ b/src/client/views/nodes/KeyValuePair.scss @@ -1,4 +1,4 @@ -@import "../globalCssVariables"; +@import "../global/globalCssVariables"; .keyValuePair-td-key { diff --git a/src/client/views/nodes/PDFBox.scss b/src/client/views/nodes/PDFBox.scss index 0f46da294..72dec6e4c 100644 --- a/src/client/views/nodes/PDFBox.scss +++ b/src/client/views/nodes/PDFBox.scss @@ -7,7 +7,7 @@ overflow: hidden; cursor: auto; transform-origin: top left; - z-index: 0; + //z-index: 0; .pdfBox-ui { position: absolute; @@ -30,6 +30,7 @@ justify-content: center; border-radius: 3px; pointer-events: all; + z-index: 1; // so it appears on top of the document's title, if shown } .pdfBox-pageNums { @@ -223,7 +224,7 @@ .pdfBox { width: 100%; height: 100%; - pointer-events: none; + //pointer-events: none; .pdfViewerDash-text { .textLayer { display: none; diff --git a/src/client/views/nodes/PresBox.scss b/src/client/views/nodes/PresBox.scss index 1ba86232b..5d1c5f4eb 100644 --- a/src/client/views/nodes/PresBox.scss +++ b/src/client/views/nodes/PresBox.scss @@ -1,7 +1,4 @@ -$light-blue: #AEDDF8; -$dark-blue: #5B9FDD; -$light-background: #ececec; -$dark-grey: #656565; +@import "../global/globalCssVariables"; .presBox-cont { cursor: auto; @@ -10,7 +7,6 @@ $dark-grey: #656565; pointer-events: inherit; z-index: 2; font-family: Roboto; - box-shadow: #AAAAAA .2vw .2vw .4vw; width: 100%; min-width: 20px; height: 100%; @@ -47,8 +43,8 @@ $dark-grey: #656565; align-items: center; height: 30px; width: 100%; - color: white; - background-color: #323232; + color: $white; + background-color: $dark-gray; .toolbar-button { cursor: pointer; @@ -110,7 +106,7 @@ $dark-grey: #656565; } .toolbar-divider { - border-left: solid #ffffff70 0.5px; + border-left: solid $medium-gray 0.5px; height: 20px; } } @@ -118,7 +114,7 @@ $dark-grey: #656565; .dropdown { font-size: 10; margin-left: 5px; - color: darkgrey; + color: $medium-gray; transition: 0.5s ease; } @@ -174,7 +170,7 @@ $dark-grey: #656565; .ribbon-colorBox { cursor: pointer; - border: solid 1px black; + border: solid 1px $black; display: flex; margin-left: 5px; margin-top: 5px; @@ -191,9 +187,9 @@ $dark-grey: #656565; font-size: 11; font-weight: 200; height: 20; - background-color: #ececec; - color: black; - border: solid 1px black; + background-color: $white; + color: $black; + border: solid 1px $black; display: flex; margin-left: 5px; margin-top: 5px; @@ -220,11 +216,11 @@ $dark-grey: #656565; align-items: center; height: 100%; width: 100%; - background: black; + background: $black; } .ribbon-propertyUpDownItem:hover { - background: darkgrey; + background: $medium-gray; transform: scale(1.05); } } @@ -239,7 +235,7 @@ $dark-grey: #656565; .multiThumb-slider { display: grid; - background-color: $light-background; + background-color: $white; height: 10px; border-radius: 10px; overflow: hidden; @@ -257,8 +253,8 @@ $dark-grey: #656565; -webkit-appearance: none; height: 10px; cursor: ew-resize; - background: $dark-blue; - box-shadow: -100vw 0 0 100vw $light-background; + background: $medium-blue; + box-shadow: -100vw 0 0 100vw $white; } .toolbar-slider.end::-webkit-slider-thumb { @@ -267,7 +263,7 @@ $dark-grey: #656565; -webkit-appearance: none; height: 10px; cursor: ew-resize; - background: $dark-blue; + background: $medium-blue; box-shadow: -100vw 0 0 100vw $light-blue; } } @@ -282,7 +278,7 @@ $dark-grey: #656565; height: 10px; border-radius: 10px; -webkit-appearance: none; - background-color: $light-background; + background-color: $white; } .toolbar-slider:focus { @@ -301,7 +297,7 @@ $dark-grey: #656565; -webkit-appearance: none; height: 10px; cursor: ew-resize; - background: $dark-blue; + background: $medium-blue; box-shadow: -100vw 0 0 100vw $light-blue; } @@ -318,7 +314,7 @@ $dark-grey: #656565; width: 15px; min-width: 15px; cursor: pointer; - background: $light-background; + background: $white; } .presBox-checkbox:focus { @@ -326,7 +322,7 @@ $dark-grey: #656565; } .presBox-checkbox:hover { - background: #c0c0c0; + background: $light-gray; } .presBox-checkbox:checked { @@ -381,9 +377,9 @@ $dark-grey: #656565; text-align: center; font-size: 16; width: 90%; - color: black; + color: $black; transform: translate(5%, 0px); - border-bottom: solid 2px darkgrey; + border-bottom: solid 2px $medium-gray; } @@ -396,8 +392,8 @@ $dark-grey: #656565; justify-self: left; margin-top: 5px; padding-left: 10px; - background-color: $light-background; - border: solid 1px black; + background-color: $white; + border: solid 1px $black; min-width: 80px; max-width: 200px; width: 100%; @@ -416,7 +412,7 @@ $dark-grey: #656565; } .ribbon-frameSelector { - border: black solid 1px; + border: $black solid 1px; width: 60px; height: 20px; margin-top: 5px; @@ -433,12 +429,12 @@ $dark-grey: #656565; cursor: pointer; position: relative; height: 100%; - background: $light-background; + background: $white; display: flex; align-items: center; justify-content: center; text-align: center; - color: black; + color: $black; } .numKeyframe { @@ -446,7 +442,7 @@ $dark-grey: #656565; font-size: 10; font-weight: 600; position: relative; - color: black; + color: $black; display: flex; width: 100%; height: 100%; @@ -489,7 +485,7 @@ $dark-grey: #656565; padding-left: 10; padding-right: 10; border-radius: 10px; - background-color: #979797; + background-color: $medium-gray; } .ribbon-final-button:hover { @@ -508,13 +504,13 @@ $dark-grey: #656565; align-items: center; margin-bottom: 5px; height: 25px; - color: lightgrey; + color: $light-gray; width: 100%; max-width: 120; padding-left: 10; padding-right: 10; border-radius: 10px; - background-color: black; + background-color: $black; } .ribbon-final-button-hidden:hover { @@ -525,15 +521,15 @@ $dark-grey: #656565; .ribbon-frameList { width: calc(100% - 5px); height: 50px; - background-color: #ececec; - border: 1px solid #9f9f9f; + background-color: $white; + border: 1px solid $medium-gray; grid-template-rows: max-content; .frameList-header { display: grid; width: 100%; height: 20px; - background-color: #9f9f9f; + background-color: $medium-gray; .frameList-headerButtons { display: flex; @@ -588,7 +584,7 @@ $dark-grey: #656565; font-size: 10.5; font-weight: 300; height: 20; - background-color: #979797; + background-color: $medium-gray; color: white; display: flex; margin-top: 5px; @@ -607,8 +603,8 @@ $dark-grey: #656565; transition: all 0.4s; font-weight: 400; opacity: 1; - color: white; - background-color: black; + color: $white; + background-color: $black; } .ribbon-toggle { @@ -616,10 +612,10 @@ $dark-grey: #656565; font-size: 10.5; font-weight: 200; height: 20; - background-color: $light-background; + background-color: $white; border: solid 1px rgba(0, 0, 0, 0.5); display: flex; - color: black; + color: $black; margin-top: 5px; margin-bottom: 5px; border-radius: 5px; @@ -660,13 +656,13 @@ $dark-grey: #656565; position: relative; font-size: 13; padding-bottom: 10px; - border-bottom: solid 1px $dark-grey; + border-bottom: solid 1px $dark-gray; .presBox-dropdown:hover { - border: solid 1px $dark-blue; + border: solid 1px $medium-blue; .presBox-dropdownIcon { - color: $dark-blue; + color: $medium-blue; } } @@ -675,12 +671,12 @@ $dark-grey: #656565; display: grid; grid-template-columns: auto 20%; position: relative; - border: solid 1px black; - background-color: $light-background; + border: solid 1px $black; + background-color: $light-gray; border-radius: 5px; font-size: 10; height: 25; - color: black; + color: $black; padding-left: 5px; align-items: center; margin-top: 5px; @@ -744,7 +740,7 @@ $dark-grey: #656565; height: 100px; padding-top: 5px; padding-bottom: 5px; - border: solid 1px black; + border: solid 1px $black; // overflow: auto; ::-webkit-scrollbar { @@ -794,7 +790,7 @@ $dark-grey: #656565; cursor: pointer; position: relative; text-align: center; - border-left: solid 1px darkgrey; + border-left: solid 1px $medium-gray; width: 20%; height: 100%; display: flex; @@ -825,7 +821,7 @@ $dark-grey: #656565; box-shadow: 0px 4px 10px rgba(0, 0, 0, 0.8); z-index: 200; background-color: white; - color: black; + color: $black; position: absolute; overflow: hidden; } @@ -841,12 +837,12 @@ $dark-grey: #656565; align-items: center; justify-content: center; transform: translate(0px, -1px); - background-color: $light-background; + background-color: $white; width: 40px; height: 15px; align-self: center; justify-self: center; - border: solid 1px black; + border: solid 1px $black; border-top: 0px; border-bottom-right-radius: 7px; border-bottom-left-radius: 7px; @@ -855,15 +851,15 @@ $dark-grey: #656565; .layout-container { padding: 5px; display: grid; - background-color: $light-background; + background-color: $white; grid-template-columns: repeat(auto-fit, minmax(90px, 100px)); width: 100%; - border: solid 1px black; + border: solid 1px $black; min-width: 100px; overflow: hidden; .layout:hover { - border: solid 2px #5c9edd; + border: solid 2px $medium-blue; } .layout { @@ -878,7 +874,7 @@ $dark-grey: #656565; width: 90px; overflow: hidden; background-color: white; - border: solid darkgrey 1px; + border: solid $medium-gray 1px; display: grid; grid-template-rows: auto; align-items: center; @@ -893,7 +889,7 @@ $dark-grey: #656565; height: 13; font-size: 12; display: flex; - background-color: #f1efec; + background-color: #white; } .subtitle { @@ -906,7 +902,7 @@ $dark-grey: #656565; height: 13; font-size: 9; display: flex; - background-color: #f1efec; + background-color: $white; } .content { @@ -919,7 +915,7 @@ $dark-grey: #656565; height: 13; font-size: 10; display: flex; - background-color: #f1efec; + background-color: $white; height: 33; text-align: left; font-size: 8px; @@ -960,8 +956,8 @@ $dark-grey: #656565; select { - background: #323232; - color: white; + background: $dark-gray; + color: $white; } .presBox-button { @@ -975,8 +971,8 @@ $dark-grey: #656565; text-align: center; letter-spacing: normal; width: inherit; - background: #323232; - color: white; + background: $dark-gray; + color: $white; } .presBox-button.active { @@ -984,7 +980,7 @@ $dark-grey: #656565; } .presBox-button.active:hover { - background-color: #233163; + background-color: $medium-blue; } .presBox-button.edit { @@ -1053,8 +1049,8 @@ $dark-grey: #656565; font-size: 100; display: flex; align-items: center; - background: #323232; - color: white; + background: $dark-gray; + color: $white; } .presBox-viewPicker { @@ -1086,7 +1082,7 @@ $dark-grey: #656565; top: 10; opacity: 0.1; transition: all 0.4s; - color: white; + color: $white; } .miniPres:hover { @@ -1094,8 +1090,8 @@ $dark-grey: #656565; } .presPanelOverlay { - background-color: #323232; - color: white; + background-color: $dark-gray; + color: $white; border-radius: 5px; grid-template-rows: 100%; height: 25; @@ -1129,7 +1125,7 @@ $dark-grey: #656565; .presPanel-divider { width: 0.5px; height: 80%; - border-right: solid 1px #5a5a5a; + border-right: solid 1px $medium-gray; } .presPanel-button-frame { @@ -1161,12 +1157,12 @@ $dark-grey: #656565; } .presPanel-button:hover { - background-color: #5a5a5a; + background-color: $medium-gray; transform: scale(1.2); } .presPanel-button-text:hover { - background-color: #5a5a5a; + background-color: $medium-gray; } diff --git a/src/client/views/nodes/RadialMenu.scss b/src/client/views/nodes/RadialMenu.scss index daa620d12..312b51013 100644 --- a/src/client/views/nodes/RadialMenu.scss +++ b/src/client/views/nodes/RadialMenu.scss @@ -1,4 +1,4 @@ -@import "../globalCssVariables"; +@import "../global/globalCssVariables"; .radialMenu-cont { position: absolute; @@ -53,7 +53,7 @@ s transition: all .1s; border-width: .11px; border-style: none; - border-color: $intermediate-color; // rgb(187, 186, 186); + border-color: $medium-gray; // rgb(187, 186, 186); // padding: 10px 0px 10px 0px; white-space: nowrap; font-size: 13px; diff --git a/src/client/views/nodes/WebBox.scss b/src/client/views/nodes/WebBox.scss index ca82c049c..19b69ff5a 100644 --- a/src/client/views/nodes/WebBox.scss +++ b/src/client/views/nodes/WebBox.scss @@ -1,4 +1,4 @@ -@import "../globalCssVariables.scss"; +@import "../global/globalCssVariables.scss"; .webBox { @@ -17,6 +17,7 @@ justify-content: center; border-radius: 3px; pointer-events: all; + z-index: 1; // so it appears on top of the document's title, if shown } .pdfViewerDash-dragAnnotationBox { diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.scss b/src/client/views/nodes/formattedText/FormattedTextBox.scss index 53aceb533..3cedab1a4 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.scss +++ b/src/client/views/nodes/formattedText/FormattedTextBox.scss @@ -1,4 +1,4 @@ -@import "../../globalCssVariables"; +@import "../../global/globalCssVariables"; .ProseMirror { width: 100%; @@ -31,7 +31,7 @@ audiotag:hover { padding: 0; border-width: 0px; border-radius: inherit; - border-color: $intermediate-color; + border-color: $medium-gray; box-sizing: border-box; background-color: inherit; border-style: solid; @@ -363,7 +363,7 @@ footnote::after { @media only screen and (max-width: 1000px) { - @import "../../globalCssVariables"; + @import "../../global/globalCssVariables"; .ProseMirror { width: 100%; @@ -381,7 +381,7 @@ footnote::after { padding: 0; border-width: 0px; border-radius: inherit; - border-color: $intermediate-color; + border-color: $medium-gray; box-sizing: border-box; background-color: inherit; border-style: solid; diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx index 95d8f555c..6dd63fb47 100644 --- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx +++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx @@ -71,6 +71,7 @@ export interface FormattedTextBoxProps { xPadding?: number; // used to override document's settings for xMargin --- see CollectionCarouselView yPadding?: number; noSidebar?: boolean; + dontScale?: boolean; dontSelectOnLoad?: boolean; // suppress selecting the text box when loaded (and mark as not being associated with scrollTop document field) } export const GoogleRef = "googleDocId"; @@ -126,7 +127,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp @computed get scrollHeight() { return NumCast(this.rootDoc[this.fieldKey + "-scrollHeight"]); } @computed get sidebarHeight() { return !this.sidebarWidth() ? 0 : NumCast(this.rootDoc[this.SidebarKey + "-height"]); } @computed get titleHeight() { return this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.HeaderMargin) || 0; } - @computed get autoHeightMargins() { return this.titleHeight + (this.layoutDoc._autoHeightMargins && !this.props.dontSelectOnLoad ? NumCast(this.layoutDoc._autoHeightMargins) : 0); } + @computed get autoHeightMargins() { return this.titleHeight + NumCast(this.layoutDoc._autoHeightMargins); } @computed get _recording() { return this.dataDoc?.mediaState === "recording"; } set _recording(value) { !this.dataDoc.recordingSource && (this.dataDoc.mediaState = value ? "recording" : undefined); @@ -1524,10 +1525,10 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<(FieldViewProp <div className="formattedTextBox-cont" onWheel={e => this.isContentActive() && e.stopPropagation()} style={{ - transform: `scale(${scale})`, - transformOrigin: "top left", - width: `${100 / scale}%`, - height: `${100 / scale}%`, + transform: this.props.dontScale ? undefined : `scale(${scale})`, + transformOrigin: this.props.dontScale ? undefined : "top left", + width: this.props.dontScale ? undefined : `${100 / scale}%`, + height: this.props.dontScale ? undefined : `${100 / scale}%`, // overflowY: this.layoutDoc._autoHeight ? "hidden" : undefined, ...this.styleFromLayoutString(scale) // this converts any expressions in the format string to style props. e.g., <FormattedTextBox height='{this._headerHeight}px' > }}> diff --git a/src/client/views/nodes/formattedText/RichTextMenu.scss b/src/client/views/nodes/formattedText/RichTextMenu.scss index 1d24d6833..c94e93541 100644 --- a/src/client/views/nodes/formattedText/RichTextMenu.scss +++ b/src/client/views/nodes/formattedText/RichTextMenu.scss @@ -1,4 +1,4 @@ -@import "../../globalCssVariables"; +@import "../../global/globalCssVariables"; .button-dropdown-wrapper { position: relative; @@ -24,7 +24,7 @@ top: 35px; left: 0; background-color: #323232; - color: $light-color-secondary; + color: $light-gray; border: 1px solid #4d4d4d; border-radius: 0 6px 6px 6px; box-shadow: 3px 3px 3px rgba(0, 0, 0, 0.25); diff --git a/src/client/views/nodes/formattedText/TooltipTextMenu.scss b/src/client/views/nodes/formattedText/TooltipTextMenu.scss index 0e4b752ac..8c4d77da9 100644 --- a/src/client/views/nodes/formattedText/TooltipTextMenu.scss +++ b/src/client/views/nodes/formattedText/TooltipTextMenu.scss @@ -1,4 +1,4 @@ -@import "../views/globalCssVariables"; +@import "../views/global/globalCssVariables"; .ProseMirror-menu-dropdown-wrap { display: inline-block; position: relative; @@ -50,7 +50,7 @@ padding: 3px; &:hover { - background-color: $light-color-secondary; + background-color: $light-gray; } } } @@ -294,9 +294,9 @@ top: 31px; background-color: #323232; border: 1px solid #4d4d4d; - color: $light-color-secondary; + color: $light-gray; // border: none; - // border: 1px solid $light-color-secondary; + // border: 1px solid $light-gray; border-radius: 0 6px 6px 6px; padding: 3px; box-shadow: 3px 3px 3px rgba(0, 0, 0, 0.25); @@ -323,7 +323,7 @@ } .separated-button { - border-top: 1px solid $light-color-secondary; + border-top: 1px solid $light-gray; padding-top: 6px; } diff --git a/src/client/views/search/CheckBox.scss b/src/client/views/search/CheckBox.scss index cc858bec6..2a0085ade 100644 --- a/src/client/views/search/CheckBox.scss +++ b/src/client/views/search/CheckBox.scss @@ -1,4 +1,4 @@ -@import "../globalCssVariables"; +@import "../global/globalCssVariables"; .checkboxfilter { display: flex; @@ -13,7 +13,7 @@ margin-top: 0px; .check-container:hover~.check-box { - background-color: $darker-alt-accent; + background-color: $medium-blue; } .check-container { @@ -40,7 +40,7 @@ overflow: visible; background-color: transparent; border-style: solid; - border-color: $alt-accent; + border-color: $medium-gray; border-width: 2px; -webkit-transition: all 0.2s ease-in-out; -moz-transition: all 0.2s ease-in-out; diff --git a/src/client/views/search/CollectionFilters.scss b/src/client/views/search/CollectionFilters.scss index b54cdcbd1..845b16f67 100644 --- a/src/client/views/search/CollectionFilters.scss +++ b/src/client/views/search/CollectionFilters.scss @@ -1,4 +1,4 @@ -@import "../globalCssVariables"; +@import "../global/globalCssVariables"; .collection-filters { display: flex; diff --git a/src/client/views/search/IconBar.scss b/src/client/views/search/IconBar.scss index 013dcd57e..6aaf7918d 100644 --- a/src/client/views/search/IconBar.scss +++ b/src/client/views/search/IconBar.scss @@ -1,4 +1,4 @@ -@import "../globalCssVariables"; +@import "../global/globalCssVariables"; .icon-bar { display: flex; diff --git a/src/client/views/search/IconButton.scss b/src/client/views/search/IconButton.scss index 4ec03c7c9..3cb08d756 100644 --- a/src/client/views/search/IconButton.scss +++ b/src/client/views/search/IconButton.scss @@ -1,4 +1,4 @@ -@import "../globalCssVariables"; +@import "../global/globalCssVariables"; .type-outer { display: flex; @@ -9,7 +9,7 @@ .type-icon { height: 30px; width: 30px; - color: $light-color; + color: $white; // background-color: rgb(194, 194, 197); background-color: gray; border-radius: 50%; @@ -43,7 +43,7 @@ .type-icon:hover { transform: scale(1.1); - background-color: $darker-alt-accent; + background-color: $medium-blue; opacity: 1; +.filter-description { diff --git a/src/client/views/search/IconButton.tsx b/src/client/views/search/IconButton.tsx index 349690b20..2dd6b1b79 100644 --- a/src/client/views/search/IconButton.tsx +++ b/src/client/views/search/IconButton.tsx @@ -4,7 +4,7 @@ import { action, IReactionDisposer, observable, reaction, runInAction } from 'mo import { observer } from 'mobx-react'; import * as React from 'react'; import { DocumentType } from "../../documents/DocumentTypes"; -import '../globalCssVariables.scss'; +import '../global/globalCssVariables.scss'; import { IconBar } from './IconBar'; import "./IconButton.scss"; import "./SearchBox.scss"; @@ -104,7 +104,7 @@ export class IconButton extends React.Component<IconButtonProps>{ hoverStyle = { opacity: 1, backgroundColor: "rgb(128, 128, 128)" - //backgroundColor: "rgb(178, 206, 248)" //$darker-alt-accent + //backgroundColor: "rgb(178, 206, 248)" //$medium-blue }; render() { diff --git a/src/client/views/search/NaviconButton.scss b/src/client/views/search/NaviconButton.scss index c23bab461..8a70b29de 100644 --- a/src/client/views/search/NaviconButton.scss +++ b/src/client/views/search/NaviconButton.scss @@ -1,4 +1,4 @@ -@import "../globalCssVariables"; +@import "../global/globalCssVariables"; $height-icon: 15px; $width-line: 30px; @@ -20,7 +20,7 @@ $translateX: 0; .line { display: block; - background: $alt-accent; + background: $medium-gray; width: $width-line; height: $height-line; position: absolute; diff --git a/src/client/views/search/SearchBox.scss b/src/client/views/search/SearchBox.scss index 4f5b7e41a..6a2fe6f19 100644 --- a/src/client/views/search/SearchBox.scss +++ b/src/client/views/search/SearchBox.scss @@ -1,4 +1,4 @@ -@import "../globalCssVariables"; +@import "../global/globalCssVariables"; @import "./NaviconButton.scss"; .searchBox-container { @@ -20,7 +20,7 @@ display: flex; justify-content: center; align-items: center; - background-color: black; + background-color: $dark-gray; .searchBox-lozenges { position: absolute; @@ -86,7 +86,7 @@ &.searchBox-input { margin:5px; border-radius:20px; - border:black; + border:$dark-gray; display: block; width: 130px; -webkit-transition: width 0.4s; @@ -114,7 +114,7 @@ } &.searchBox-close { - color: $light-color; + color: $white; max-height: $searchpanel-height; } } @@ -132,7 +132,7 @@ .no-result { width: 500px; - background: $light-color-secondary; + background: $light-gray; padding: 10px; height: 50px; text-transform: uppercase; diff --git a/src/client/views/search/SelectorContextMenu.scss b/src/client/views/search/SelectorContextMenu.scss index 48cacc608..a114f679c 100644 --- a/src/client/views/search/SelectorContextMenu.scss +++ b/src/client/views/search/SelectorContextMenu.scss @@ -1,7 +1,7 @@ -@import "../globalCssVariables"; +@import "../global/globalCssVariables"; .parents { - background: $lighter-alt-accent; + background: $light-blue; padding: 10px; // width: 300px; @@ -10,7 +10,7 @@ } .collection { - border-color: $darker-alt-accent; + border-color: $medium-blue; border-bottom-style: solid; } }
\ No newline at end of file diff --git a/src/client/views/search/ToggleBar.scss b/src/client/views/search/ToggleBar.scss index 79f866acb..3a164f133 100644 --- a/src/client/views/search/ToggleBar.scss +++ b/src/client/views/search/ToggleBar.scss @@ -1,9 +1,9 @@ -@import "../globalCssVariables"; +@import "../global/globalCssVariables"; .toggle-title { display: flex; align-items: center; - color: $light-color; + color: $white; text-transform: uppercase; flex-direction: row; justify-content: space-around; @@ -25,7 +25,7 @@ // height: 50px; height: 30px; width: 100px; - background-color: $alt-accent; + background-color: $medium-gray; border-radius: 10px; padding: 5px; display: flex; @@ -36,6 +36,6 @@ width: 40px; height: 100%; border-radius: 10px; - background-color: $light-color; + background-color: $white; } }
\ No newline at end of file diff --git a/src/client/views/webcam/DashWebRTCVideo.scss b/src/client/views/webcam/DashWebRTCVideo.scss index 41307a808..249aee9d6 100644 --- a/src/client/views/webcam/DashWebRTCVideo.scss +++ b/src/client/views/webcam/DashWebRTCVideo.scss @@ -1,4 +1,4 @@ -@import "../globalCssVariables"; +@import "../global/globalCssVariables"; .webcam-cont { background: whitesmoke; diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts index bd0ba3ad7..464a8ad05 100644 --- a/src/fields/Doc.ts +++ b/src/fields/Doc.ts @@ -803,6 +803,27 @@ export namespace Doc { return undefined; } + // Makes a delegate of a document by first creating a delegate where data should be stored + // (ie, the 'data' doc), and then creates another delegate of that (ie, the 'layout' doc). + // This is appropriate if you're trying to create a document that behaves like all + // regularly created documents (e.g, text docs, pdfs, etc which all have data/layout docs) + export function MakeDelegateWithProto(doc: Doc, id?: string, title?: string): Doc { + const delegateProto = new Doc(); + delegateProto[Initializing] = true; + delegateProto.proto = doc; + delegateProto.author = Doc.CurrentUserEmail; + delegateProto.isPrototype = true; + title && (delegateProto.title = title); + const delegate = new Doc(id, true); + delegate[Initializing] = true; + delegate.proto = delegateProto; + delegate.author = Doc.CurrentUserEmail; + Doc.AddDocToList(delegateProto[DataSym], "aliases", delegate); + delegate[Initializing] = false; + delegateProto[Initializing] = false; + return delegate; + } + let _applyCount: number = 0; export function ApplyTemplate(templateDoc: Doc) { if (templateDoc) { @@ -1150,8 +1171,7 @@ export namespace Doc { return ndoc; } export function delegateDragFactory(dragFactory: Doc) { - const ndoc = Doc.MakeDelegate(dragFactory); - ndoc.isPrototype = true; + const ndoc = Doc.MakeDelegateWithProto(dragFactory); if (ndoc && dragFactory["dragFactory-count"] !== undefined) { dragFactory["dragFactory-count"] = NumCast(dragFactory["dragFactory-count"]) + 1; Doc.GetProto(ndoc).title = ndoc.title + " " + NumCast(dragFactory["dragFactory-count"]).toString(); diff --git a/src/fields/InkField.ts b/src/fields/InkField.ts index dbe51b24a..1270a2dab 100644 --- a/src/fields/InkField.ts +++ b/src/fields/InkField.ts @@ -4,6 +4,7 @@ import { ObjectField } from "./ObjectField"; import { Copy, ToScriptString, ToString, Update } from "./FieldSymbols"; import { Scripting } from "../client/util/Scripting"; +// Helps keep track of the current ink tool in use. export enum InkTool { None = "none", Pen = "pen", @@ -12,13 +13,41 @@ export enum InkTool { Stamp = "stamp" } + +// Defines a point in an ink as a pair of x- and y-coordinates. export interface PointData { X: number; Y: number; } +// Defines an ink as an array of points. export type InkData = Array<PointData>; +export interface ControlPoint { + X: number; + Y: number; + I: number; +} + +export interface HandlePoint { + X: number; + Y: number; + I: number; + dot1: number; + dot2: number; +} + +export interface HandleLine { + X1: number; + Y1: number; + X2: number; + Y2: number; + X3: number; + Y3: number; + dot1: number; + dot2: number; +} + const pointSchema = createSimpleSchema({ X: true, Y: true }); @@ -32,8 +61,6 @@ const strokeDataSchema = createSimpleSchema({ export class InkField extends ObjectField { @serializable(list(object(strokeDataSchema))) readonly inkData: InkData; - // inkData: InkData; - constructor(data: InkData) { super(); diff --git a/src/mobile/AudioUpload.scss b/src/mobile/AudioUpload.scss index 6e64d9e2e..dce0c724f 100644 --- a/src/mobile/AudioUpload.scss +++ b/src/mobile/AudioUpload.scss @@ -1,4 +1,4 @@ -@import "../client/views/globalCssVariables.scss"; +@import "../client/views/global/globalCssVariables.scss"; .audioUpload_cont { display: flex; diff --git a/src/mobile/ImageUpload.scss b/src/mobile/ImageUpload.scss index 890258918..6669a3d21 100644 --- a/src/mobile/ImageUpload.scss +++ b/src/mobile/ImageUpload.scss @@ -1,4 +1,4 @@ -@import "../client/views/globalCssVariables.scss"; +@import "../client/views/global/globalCssVariables.scss"; .imgupload_cont { display: flex; diff --git a/src/mobile/ImageUpload.tsx b/src/mobile/ImageUpload.tsx index 2183d2172..98696496f 100644 --- a/src/mobile/ImageUpload.tsx +++ b/src/mobile/ImageUpload.tsx @@ -5,7 +5,7 @@ import * as rp from 'request-promise'; import { DocServer } from '../client/DocServer'; import { Docs } from '../client/documents/Documents'; import { Networking } from '../client/Network'; -import { DFLT_IMAGE_NATIVE_DIM } from '../client/views/globalCssVariables.scss'; +import { DFLT_IMAGE_NATIVE_DIM } from '../client/views/global/globalCssVariables.scss'; import { MainViewModal } from '../client/views/MainViewModal'; import { Doc, Opt } from '../fields/Doc'; import { List } from '../fields/List'; diff --git a/src/server/DashSession/Session/agents/server_worker.ts b/src/server/DashSession/Session/agents/server_worker.ts index 6a19bfa5d..60fc181c7 100644 --- a/src/server/DashSession/Session/agents/server_worker.ts +++ b/src/server/DashSession/Session/agents/server_worker.ts @@ -1,10 +1,10 @@ -import { ExitHandler } from "./applied_session_agent"; import { isMaster } from "cluster"; -import { manage, ErrorLike } from "./promisified_ipc_manager"; -import IPCMessageReceiver from "./process_message_router"; -import { red, green, white, yellow } from "colors"; +import { green, red, white, yellow } from "colors"; import { get } from "request-promise"; +import { ExitHandler } from "./applied_session_agent"; import { Monitor } from "./monitor"; +import IPCMessageReceiver from "./process_message_router"; +import { ErrorLike, manage } from "./promisified_ipc_manager"; /** * Effectively, each worker repairs the connection to the server by reintroducing a consistent state |