aboutsummaryrefslogtreecommitdiff
path: root/src/client/util
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/util')
-rw-r--r--src/client/util/CalendarManager.tsx2
-rw-r--r--src/client/util/CurrentUserUtils.ts174
-rw-r--r--src/client/util/DictationManager.ts5
-rw-r--r--src/client/util/DocumentManager.ts37
-rw-r--r--src/client/util/GroupManager.tsx2
-rw-r--r--src/client/util/GroupMemberView.tsx2
-rw-r--r--src/client/util/InteractionUtils.tsx6
-rw-r--r--src/client/util/LinkFollower.ts2
-rw-r--r--src/client/util/SelectionManager.ts3
-rw-r--r--src/client/util/SettingsManager.tsx28
-rw-r--r--src/client/util/SharingManager.tsx2
-rw-r--r--src/client/util/SnappingManager.ts7
-rw-r--r--src/client/util/bezierFit.ts11
-rw-r--r--src/client/util/reportManager/ReportManager.tsx2
14 files changed, 169 insertions, 114 deletions
diff --git a/src/client/util/CalendarManager.tsx b/src/client/util/CalendarManager.tsx
index d0cd69273..d28b3a2c9 100644
--- a/src/client/util/CalendarManager.tsx
+++ b/src/client/util/CalendarManager.tsx
@@ -2,7 +2,7 @@ import { DateRangePicker, Provider, defaultTheme } from '@adobe/react-spectrum';
import { IconLookup, faPlus } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { TextField } from '@mui/material';
-import { Button } from 'browndash-components';
+import { Button } from '@dash/components';
import { action, computed, makeObservable, observable, runInAction } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index 30c75c659..0783bb80e 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -4,7 +4,7 @@ import * as rp from 'request-promise';
import { ClientUtils, OmitKeys } from "../../ClientUtils";
import { Doc, DocListCast, DocListCastAsync, FieldType, Opt } from "../../fields/Doc";
import { DocData } from "../../fields/DocSymbols";
-import { InkTool } from "../../fields/InkField";
+import { InkEraserTool, InkInkTool, InkProperty, InkTool } from "../../fields/InkField";
import { List } from "../../fields/List";
import { PrefetchProxy } from "../../fields/Proxy";
import { RichTextField } from "../../fields/RichTextField";
@@ -39,6 +39,8 @@ import { SelectionManager } from "./SelectionManager";
import { ColorScheme } from "./SettingsManager";
import { SnappingManager } from "./SnappingManager";
import { UndoManager } from "./UndoManager";
+import { DocumentView } from "../views/nodes/DocumentView";
+import { IconProp } from "@fortawesome/fontawesome-svg-core";
export interface Button {
// DocumentOptions fields a button can set
@@ -66,6 +68,21 @@ export interface Button {
subMenu?: Button[];
}
+// Not really necessary, but for now, all tags should start with a capital first letter
+export type TagName<T extends string> =
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
+ T extends `${infer First}${infer Rest}`
+ ? First extends Uppercase<First>
+ ? First extends Lowercase<First>
+ ? never // If it's the same when uppercased and lowercased, it's not a letter.
+ : T // Otherwise, it's a valid capitalized string.
+ : never
+ : never;
+export function ToTagName(key: string):"Tag"{
+ return ((str => str[0].toUpperCase() + str.slice(1))(key.startsWith('#') ? key.substring(1) : key)) as "Tag";
+}
+
+
export let resolvedPorts: { server: number, socket: number };
export class CurrentUserUtils {
@@ -160,9 +177,9 @@ export class CurrentUserUtils {
return DocUtils.AssignDocField(doc, field, (opts,items) => Docs.Create.TreeDocument(items??[], opts), reqdOpts, templates, reqdScripts);
}
- static setupAnnoPalette(doc: Doc, field="myAnnos") {
+ static setupAnnoPalette(doc: Doc, field="myStickers") {
const reqdOpts:DocumentOptions = {
- title: "Saved Annotations", _xMargin: 0, _layout_showTitle: "title", hidden: false, _chromeHidden: true,
+ title: "Stickers", _xMargin: 0, _layout_showTitle: "title", hidden: false, _chromeHidden: true,
_dragOnlyWithinContainer: true, layout_hideContextMenu: true, isSystem: true, _forceActive: true,
_layout_autoHeight: true, _width: 500, _height: 300, _layout_fitWidth: true, _columnWidth: 35, ignoreClick: true, _lockedPosition: true,
};
@@ -186,7 +203,7 @@ export class CurrentUserUtils {
const templateIconsDoc = DocUtils.AssignOpts(DocCast(doc[field]), reqdOpts) ?? (doc[field] = Docs.Create.TreeDocument([], reqdOpts));
const labelBox = (opts: DocumentOptions, fieldKey:string) => Docs.Create.LabelDocument({
- layout: LabelBox.LayoutString(fieldKey), textTransform: "unset", letterSpacing: "unset", _singleLine: false, _label_minFontSize: 14, _label_maxFontSize: 14, layout_borderRounding: "5px", _width: 150, _height: 70, _xPadding: 10, _yPadding: 10, ...opts
+ layout: LabelBox.LayoutString(fieldKey), letterSpacing: "unset", _label_minFontSize: 14, _label_maxFontSize: 14, layout_borderRounding: "5px", _width: 150, _height: 70, _xPadding: 10, _yPadding: 10, ...opts
});
const imageBox = (opts: DocumentOptions, fieldKey:string) => Docs.Create.ImageDocument( "http://www.cs.brown.edu/~bcz/noImage.png", { layout:ImageBox.LayoutString(fieldKey), "icon_nativeWidth": 360 / 4, "icon_nativeHeight": 270 / 4, iconTemplate:DocumentType.IMG, _width: 360 / 4, _height: 270 / 4, _layout_showTitle: "title", ...opts });
const fontBox = (opts:DocumentOptions, fieldKey:string) => Docs.Create.FontIconDocument({ layout:FontIconBox.LayoutString(fieldKey), _nativeHeight: 30, _nativeWidth: 30, _width: 30, _height: 30, ...opts });
@@ -268,7 +285,7 @@ export class CurrentUserUtils {
MakeTemplate(Docs.Create.MultirowDocument(
[
Docs.Create.MulticolumnDocument([], { title: "hero", _height: 200, isSystem: true }),
- Docs.Create.TextDocument("", { title: "text", _layout_fitWidth:true, _height: 100, isSystem: true, _text_fontFamily: StrCast(Doc.UserDoc().fontFamily), _text_fontSize: StrCast(Doc.UserDoc().fontSize) })
+ Docs.Create.TextDocument("", { title: "text", _layout_fitWidth:true, _height: 100, isSystem: true, text_fontFamily: StrCast(Doc.UserDoc().fontFamily), text_fontSize: StrCast(Doc.UserDoc().fontSize) })
], {...opts, title: "Slide View Template"}));
const plotlyApi = () => {
let plotly = Doc.MyPublishedDocs.find(fdoc => fdoc.title === "@plotly");
@@ -371,13 +388,13 @@ pie title Minerals in my tap water
{key: "Note", creator: opts => Docs.Create.TextDocument("", opts), opts: { _width: 200, _layout_autoHeight: true }},
{key: "Flashcard", creator: opts => Docs.Create.FlashcardDocument("", undefined, undefined, opts),opts: { _width: 300, _height: 300}},
{key: "Image", creator: opts => Docs.Create.ImageDocument("", opts), opts: { _width: 400, _height:400 }},
- {key: "Equation", creator: opts => Docs.Create.EquationDocument("",opts), opts: { _width: 300, _height: 35, }},
+ {key: "Equation", creator: opts => Docs.Create.EquationDocument("",opts), opts: { _width: 50, _height: 50, nativeWidth: 40, nativeHeight: 40, _xMargin: 10, _yMargin: 10}},
{key: "Noteboard", creator: opts => Docs.Create.NoteTakingDocument([], opts), opts: { _width: 250, _height: 200, _layout_fitWidth: true}},
{key: "Simulation", creator: opts => Docs.Create.SimulationDocument(opts), opts: { _width: 300, _height: 300, }},
{key: "Collection", creator: opts => Docs.Create.FreeformDocument([], opts), opts: { _width: 150, _height: 100, _layout_fitWidth: true }},
{key: "Webpage", creator: opts => Docs.Create.WebDocument("",opts), opts: { _width: 400, _height: 512, _nativeWidth: 850, data_useCors: true, }},
{key: "Comparison", creator: opts => Docs.Create.ComparisonDocument("", opts), opts: { _width: 300, _height: 300 }},
- {key: "Diagram", creator: Docs.Create.DiagramDocument, opts: { _width: 300, _height: 300, _type_collection: CollectionViewType.Freeform, layout_diagramEditor: CollectionView.LayoutString("data") }, scripts: { onPaint: `toggleDetail(documentView, "diagramEditor","")`}},
+ {key: "Diagram", creator: opts => Docs.Create.DiagramDocument("", opts), opts: { _width: 300, _height: 300, _type_collection: CollectionViewType.Freeform, layout_diagramEditor: CollectionView.LayoutString("data") }, scripts: { onPaint: `toggleDetail(documentView, "diagramEditor","")`}},
{key: "Audio", creator: opts => Docs.Create.AudioDocument(nullAudio, opts),opts: { _width: 200, _height: 100, }},
{key: "Audio", creator: opts => Docs.Create.AudioDocument(nullAudio, opts),opts: { _width: 200, _height: 100, _layout_fitWidth: true, }},
{key: "Map", creator: opts => Docs.Create.MapDocument([], opts), opts: { _width: 800, _height: 600, _layout_fitWidth: true, }},
@@ -392,7 +409,7 @@ pie title Minerals in my tap water
{key: "Trail", creator: Docs.Create.PresDocument, opts: { _width: 400, _height: 30, _type_collection: CollectionViewType.Stacking, _layout_dontCenter:'xy', dropAction: dropActionType.embed, treeView_HideTitle: true, _layout_fitWidth:true, layout_boxShadow: "0 0" }},
{key: "Tab", creator: opts => Docs.Create.FreeformDocument([], opts), opts: { _width: 500, _height: 800, _layout_fitWidth: true, _freeform_backgroundGrid: true, }},
{key: "Slide", creator: opts => Docs.Create.TreeDocument([], opts), opts: { _width: 300, _height: 200, _type_collection: CollectionViewType.Tree,
- treeView_HasOverlay: true, _text_fontSize: "20px", _layout_autoHeight: true,
+ treeView_HasOverlay: true, text_fontSize: "20px", _layout_autoHeight: true,
dropAction:dropActionType.move, treeView_Type: TreeViewType.outline,
backgroundColor: "white", _xMargin: 0, _yMargin: 0, _createDocOnCR: true
}, funcs: {title: 'this.text?.Text'}},
@@ -687,16 +704,12 @@ pie title Minerals in my tap water
{ title: "Center", icon: "align-center", toolTip: "Center Align Stack", btnType: ButtonType.ToggleButton, ignoreClick: true, expertMode: false, toolType:"hcenter", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, // Only when floating document is selected in freeform
]
}
- static cardTools(): Button[] {
+ static sortTools(): Button[] {
return [
{ title: "Time", icon:"hourglass-half", toolTip:"Sort by most recent document creation", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"time", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}},
{ title: "Type", icon:"eye", toolTip:"Sort by document type", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"docType", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}},
{ title: "Color", icon:"palette", toolTip:"Sort by document color", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"color", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}},
{ title: "Tags", icon:"bolt", toolTip:"Sort by document's tags", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"tag", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}},
- { title: "Pile", icon:"layer-group", toolTip:"View the cards as a pile in the free form view", btnType: ButtonType.ClickButton, expertMode: false, toolType:"pile", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}},
- { title: "Chat Popup",icon:"lightbulb", toolTip:"Toggle the chat popup's visibility", width: 45, btnType: ButtonType.ToggleButton, expertMode: false, toolType:"toggle-chat",funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'} },
- { title: "Show Tags", icon:"id-card", toolTip:"Toggle tag annotation panel", width: 45, btnType: ButtonType.ToggleButton, expertMode: false, toolType:"toggle-tags",funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'} },
-
{ title: "Sort", icon: "sort" , toolTip: "Manage sort order / lock status", btnType: ButtonType.MultiToggleButton, toolType:"alignment", ignoreClick: true,
subMenu: [
{ title: "Ascending", toolTip: "Sort the cards in ascending order", btnType: ButtonType.ToggleButton, icon: "sort-up", toolType:"up", ignoreClick: true, scripts: {onClick: '{ return showFreeform(this.toolType, _readOnly_);}'} },
@@ -704,38 +717,44 @@ pie title Minerals in my tap water
]},
]
}
+
+ static filterBtnDesc<T extends string>(tag:TagName<T>|"Tag", icon:IconProp):Button {
+ return { title: tag, isSystem: false, icon: icon.toString(), toolTip:`Click to toggle visibility of ${tag} tagged Docs`, btnType: ButtonType.ToggleButton, expertMode: false, toolType:`#${tag.toLowerCase()}`, funcs: {}, scripts: { onClick: '{ return setTagFilter(this.toolType, _added_, _readOnly_);}'}}
+ }
- static tagGroupTools(): Button[] {
- const defaultTagButtonDescs = [
- { title: "Star", isSystem: false,icon: "star", toolTip:"Click to toggle visibility of Star tagged Docs", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"#star", funcs: {}, scripts: { onClick: '{ return setTagFilter(this.toolType, _added_, _readOnly_);}'}},
- { title: "Like", isSystem: false,icon: "heart", toolTip:"Click to toggle visibility of Like tagged Docs", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"#like", funcs: {}, scripts: { onClick: '{ return setTagFilter(this.toolType, _added_, _readOnly_);}'}},
- { title: "Todo", isSystem: false,icon: "bolt", toolTip:"Click to toggle visibility of Todo tagged Docs", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"#todo", funcs: {}, scripts: { onClick: '{ return setTagFilter(this.toolType, _added_, _readOnly_);}'}},
- { title: "Idea", isSystem: false,icon: "cloud", toolTip:"Click to toggle visibility of Idea tagged Docs", btnType: ButtonType.ToggleButton, expertMode: false, toolType:"#idea", funcs: {}, scripts: { onClick: '{ return setTagFilter(this.toolType, _added_, _readOnly_);}'}},
+ static filterTools(): Button[] {
+ // If there's no active dashboard, then a default set of tags are added, otherwise, the user controls which tags are kept
+ const tagButtonDescs = Doc.UserDoc().activeDashboard ? [] : [
+ this.filterBtnDesc("Star", "star"),
+ this.filterBtnDesc("Like", "heart"),
+ this.filterBtnDesc("Todo", "bolt"),
+ this.filterBtnDesc("Idea", "cloud"),
+ this.filterBtnDesc("Chat", "robot")
];
- // hack: if there's no dashboard, create default filters. otherwise, just make sure that the Options button is preserved
return [
- { title:"Options",isSystem: true,icon: "gear", toolTip:"Click to customize list of filter buttons", btnType: ButtonType.ClickButton, expertMode: false, toolType:"-opts-",funcs: {}, scripts: { onClick: '{ return setTagFilter(this.toolType, false,_readOnly_);}'}},
- ...(Doc.UserDoc().activeDashboard ? [] : defaultTagButtonDescs)
+ { title:"Options",isSystem: true,icon: "gear", toolTip:"Click to customize list of filter buttons", btnType: ButtonType.ClickButton, expertMode: false, toolType:"-opts-",funcs: {}, scripts: { onClick: '{ return setTagFilter(this.toolType, false,_readOnly_);}'}},
+ ...tagButtonDescs
]
- }
+ }
static viewTools(): Button[] {
return [
- { title: "Snap", icon: "th", toolTip: "Show Snap Lines", btnType: ButtonType.ToggleButton, ignoreClick: true, expertMode: false, toolType:"snaplines", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, // Only when floating document is selected in freeform
- { title: "Grid", icon: "border-all", toolTip: "Show Grid", btnType: ButtonType.ToggleButton, ignoreClick: true, expertMode: false, toolType:"grid", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, // Only when floating document is selected in freeform
- { title: "Fit All", icon: "object-group", toolTip: "Fit Docs to View (double click to make sticky)",btnType: ButtonType.ToggleButton, ignoreClick:true, expertMode: false, toolType:"viewAll", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}', onDoubleClick: '{ return showFreeform(this.toolType, _readOnly_, true);}'}}, // Only when floating document is selected in freeform
- { title: "Clusters", icon: "braille", toolTip: "Show Doc Clusters", btnType: ButtonType.ToggleButton, ignoreClick: true, expertMode: false, toolType:"clusters", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, // Only when floating document is selected in freeform
- { title: "Cards", icon: "brain", toolTip: "Flashcards", btnType: ButtonType.ToggleButton, ignoreClick: true, expertMode: false, toolType:"flashcards", funcs: {}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, // Only when floating document is selected in freeform
+ { title: "Show Tags", icon: "id-card", toolTip: "Toggle tags", btnType: ButtonType.ToggleButton, ignoreClick: true, expertMode: false, toolType:"toggle-tags",funcs: { }, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'} },
+ { title: "Snap", icon: "th", toolTip: "Show Snap Lines", btnType: ButtonType.ToggleButton, ignoreClick: true, expertMode: false, toolType:"snaplines", funcs: { hidden: `!SelectedDocType("${CollectionViewType.Freeform}", this.expertMode)`}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, // Only when floating document is selected in freeform
+ { title: "Grid", icon: "border-all", toolTip: "Show Grid", btnType: ButtonType.ToggleButton, ignoreClick: true, expertMode: false, toolType:"grid", funcs: { hidden: `!SelectedDocType("${CollectionViewType.Freeform}", this.expertMode)`}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, // Only when floating document is selected in freeform
+ { title: "Fit All", icon: "object-group", toolTip:"Fit Docs to View (double tap to persist)",
+ btnType: ButtonType.ToggleButton, ignoreClick: true, expertMode: false, toolType:"viewAll", funcs: { hidden: `!SelectedDocType("${CollectionViewType.Freeform}", this.expertMode)`}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}', onDoubleClick: '{ return showFreeform(this.toolType, _readOnly_, true);}'}}, // Only when floating document is selected in freeform
+ { title: "Clusters", icon: "braille", toolTip: "Show Doc Clusters", btnType: ButtonType.ToggleButton, ignoreClick: true, expertMode: false, toolType:"clusters", funcs: { hidden: `!SelectedDocType("${CollectionViewType.Freeform}", this.expertMode)`}, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'}}, // Only when floating document is selected in freeform
]
}
static textTools():Button[] {
return [
{ title: "Font", toolTip: "Font", width: 100, btnType: ButtonType.DropdownList, toolType:"font", ignoreClick: true, scripts: {script: '{ return setFontAttr(this.toolType, value, _readOnly_);}'},
- btnList: new List<string>(["Roboto", "Roboto Mono", "Nunito", "Times New Roman", "Arial", "Georgia", "Comic Sans MS", "Tahoma", "Impact", "Crimson Text"]) },
- { title: "Font Size",toolTip: "Font size (%size)", btnType: ButtonType.NumberDropdownButton, toolType:"fontSize", ignoreClick: true, scripts: {script: '{ return setFontAttr(this.toolType, value, _readOnly_);}'}, numBtnMax: 200, numBtnMin: 6 },
+ btnList: new List<string>(["Roboto", "Roboto Mono", "Nunito", "Times New Roman", "Arial", "Georgia", "Comic Sans MS", "Tahoma", "Impact", "Crimson Text", "Math"]) },
+ { title: " Size", toolTip: "Font size (%size)", btnType: ButtonType.NumberDropdownButton, toolType:"fontSize", ignoreClick: true, scripts: {script: '{ return setFontAttr(this.toolType, value, _readOnly_);}'}, numBtnMax: 200, numBtnMin: 9 },
{ title: "Color", toolTip: "Font color (%color)", btnType: ButtonType.ColorButton, icon: "font", toolType:"fontColor",ignoreClick: true, scripts: {script: '{ return setFontAttr(this.toolType, value, _readOnly_);}'} },
{ title: "Highlight",toolTip: "Font highlight", btnType: ButtonType.ColorButton, icon: "highlighter", toolType:"highlight",ignoreClick: true, scripts: {script: '{ return setFontAttr(this.toolType, value, _readOnly_);}'} },
{ title: "Bold", toolTip: "Bold (Ctrl+B)", btnType: ButtonType.ToggleButton, icon: "bold", toolType:"bold", ignoreClick: true, scripts: {onClick: '{ return toggleCharStyle(this.toolType, _readOnly_);}'} },
- { title: "Italic", toolTip: "Italic (Ctrl+I)", btnType: ButtonType.ToggleButton, icon: "italic", toolType:"italics", ignoreClick: true, scripts: {onClick: '{ return toggleCharStyle(this.toolType, _readOnly_);}'} },
+ { title: "Italic", toolTip: "Italic (Ctrl+I)", btnType: ButtonType.ToggleButton, icon: "italic", toolType:"italic", ignoreClick: true, scripts: {onClick: '{ return toggleCharStyle(this.toolType, _readOnly_);}'} },
{ title: "Under", toolTip: "Underline (Ctrl+U)", btnType: ButtonType.ToggleButton, icon: "underline", toolType:"underline",ignoreClick: true, scripts: {onClick: '{ return toggleCharStyle(this.toolType, _readOnly_);}'} },
{ title: "Bullets", toolTip: "Bullet List", btnType: ButtonType.ToggleButton, icon: "list", toolType:"bullet", ignoreClick: true, scripts: {onClick: '{ return toggleCharStyle(this.toolType, _readOnly_);}'} },
{ title: "#", toolTip: "Number List", btnType: ButtonType.ToggleButton, icon: "list-ol", toolType:"decimal", ignoreClick: true, scripts: {onClick: '{ return toggleCharStyle(this.toolType, _readOnly_);}'} },
@@ -746,6 +765,7 @@ pie title Minerals in my tap water
{ title: "Center", toolTip: "Center align (Cmd-\\)",btnType: ButtonType.ToggleButton, icon: "align-center",toolType:"center",ignoreClick: true, scripts: {onClick: '{ return toggleCharStyle(this.toolType, _readOnly_);}'} },
{ title: "Right", toolTip: "Right align (Cmd-])", btnType: ButtonType.ToggleButton, icon: "align-right", toolType:"right", ignoreClick: true, scripts: {onClick: '{ return toggleCharStyle(this.toolType, _readOnly_);}'} },
]},
+ { title: "Fit Box", toolTip: "Fit text to box", btnType: ButtonType.ToggleButton, icon: "object-group",toolType:"fitBox", ignoreClick: true, scripts: {onClick: '{ return toggleCharStyle(this.toolType, _readOnly_);}'} },
{ title: "Elide", toolTip: "Elide selection", btnType: ButtonType.ToggleButton, icon: "eye", toolType:"elide", ignoreClick: true, scripts: {onClick: '{ return toggleCharStyle(this.toolType, _readOnly_);}'} },
{ title: "Dictate", toolTip: "Dictate", btnType: ButtonType.ToggleButton, icon: "microphone", toolType:"dictation", ignoreClick: true, scripts: {onClick: '{ return toggleCharStyle(this.toolType, _readOnly_);}'} },
{ title: "NoLink", toolTip: "Auto Link", btnType: ButtonType.ToggleButton, icon: "link", toolType:"noAutoLink", expertMode:true, scripts: {onClick: '{ return toggleCharStyle(this.toolType, _readOnly_);}'}, funcs: {hidden: 'IsNoviceMode()'}},
@@ -757,24 +777,27 @@ pie title Minerals in my tap water
static inkTools():Button[] {
return [
- { title: "Pen", toolTip: "Pen (Ctrl+P)", btnType: ButtonType.ToggleButton, icon: "pen-nib", toolType: "pen", scripts: {onClick:'{ return setActiveTool(this.toolType, false, _readOnly_);}' }},
- { title: "Highlight",toolTip: "Highlight (Ctrl+H)", btnType: ButtonType.ToggleButton, icon: "highlighter",toolType: "highlighter", scripts: {onClick:'{ return setActiveTool(this.toolType, false, _readOnly_);}' }},
- { title: "Write", toolTip: "Write (Ctrl+Shift+P)", btnType: ButtonType.ToggleButton, icon: "pen", toolType: "write", scripts: {onClick:'{ return setActiveTool(this.toolType, false, _readOnly_);}' }, funcs: {hidden:"IsNoviceMode()" }},
- { title: "Eraser", toolTip: "Eraser (Ctrl+E)", btnType: ButtonType.MultiToggleButton, toolType: InkTool.Eraser, scripts: {onClick:'{ return setActiveTool(this.toolType, false, _readOnly_);}' },
+ { title: "Circle", toolTip: "Circle (double tap to lock mode)", btnType: ButtonType.ToggleButton, icon: "circle", toolType: Gestures.Circle, scripts: {onClick:`{ return setActiveTool(this.toolType, false, _readOnly_);}`, onDoubleClick:`{ return setActiveTool(this.toolType, true, _readOnly_);}`} },
+ { title: "Square", toolTip: "Square (double tap to lock mode)", btnType: ButtonType.ToggleButton, icon: "square", toolType: Gestures.Rectangle, scripts: {onClick:`{ return setActiveTool(this.toolType, false, _readOnly_);}`, onDoubleClick:`{ return setActiveTool(this.toolType, true, _readOnly_);}`} },
+ { title: "Line", toolTip: "Line (double tap to lock mode)", btnType: ButtonType.ToggleButton, icon: "minus", toolType: Gestures.Line, scripts: {onClick:`{ return setActiveTool(this.toolType, false, _readOnly_);}`, onDoubleClick:`{ return setActiveTool(this.toolType, true, _readOnly_);}`} },
+ { title: "Ink", toolTip: "Ink", btnType: ButtonType.MultiToggleButton, toolType: InkTool.Ink, scripts: {onClick:'{ return setActiveTool(this.toolType, true, _readOnly_);}' },
+ subMenu: [
+ { title: "Pen", toolTip: "Pen (Ctrl+P)", btnType: ButtonType.ToggleButton, icon: "pen-nib", toolType: InkInkTool.Pen, ignoreClick: true, scripts: {onClick:'{ return setActiveTool(this.toolType, true, _readOnly_);}' }},
+ { title: "Highlight",toolTip: "Highlight (Ctrl+H)", btnType: ButtonType.ToggleButton, icon: "highlighter", toolType: InkInkTool.Highlight, ignoreClick: true, scripts: {onClick:'{ return setActiveTool(this.toolType, true, _readOnly_);}' }},
+ { title: "Write", toolTip: "Write (Ctrl+Shift+P)", btnType: ButtonType.ToggleButton, icon: "pen", toolType: InkInkTool.Write, ignoreClick: true, scripts: {onClick:'{ return setActiveTool(this.toolType, true, _readOnly_);}' }, funcs: {hidden:"IsNoviceMode()" }},
+ ]},
+ { title: "Width", toolTip: "Stroke width", btnType: ButtonType.NumberSliderButton, toolType: InkProperty.StrokeWidth,ignoreClick: true, scripts: {script: '{ return setInkProperty(this.toolType, value, _readOnly_);}'}, funcs: {hidden:"!activeInkTool()"}, numBtnMin: 1, linearBtnWidth:40},
+ { title: "Color", toolTip: "Stroke color", btnType: ButtonType.ColorButton, icon: "pen", toolType: InkProperty.StrokeColor,ignoreClick: true, scripts: {script: '{ return setInkProperty(this.toolType, value, _readOnly_);}'}, funcs: {hidden:"!activeInkTool()"}},
+ { title: "Eraser", toolTip: "Eraser (Ctrl+E)", btnType: ButtonType.MultiToggleButton, toolType: InkTool.Eraser, scripts: {onClick:'{ return setActiveTool(this.toolType, false, _readOnly_);}' },
subMenu: [
- { title: "Stroke", toolTip: "Stroke Erase", btnType: ButtonType.ToggleButton, icon: "eraser", toolType:InkTool.StrokeEraser, ignoreClick: true, scripts: {onClick: '{ return setActiveTool(this.toolType, false, _readOnly_);}'} },
- { title: "Segment", toolTip: "Segment Erase", btnType: ButtonType.ToggleButton, icon: "xmark", toolType:InkTool.SegmentEraser,ignoreClick: true, scripts: {onClick: '{ return setActiveTool(this.toolType, false, _readOnly_);}'} },
- { title: "Radius", toolTip: "Radius Erase", btnType: ButtonType.ToggleButton, icon: "circle-xmark",toolType:InkTool.RadiusEraser, ignoreClick: true, scripts: {onClick: '{ return setActiveTool(this.toolType, false, _readOnly_);}'} },
+ { title: "Stroke", toolTip: "Eraser complete strokes",btnType: ButtonType.ToggleButton, icon: "eraser", toolType:InkEraserTool.Stroke, ignoreClick: true, scripts: {onClick: '{ return setActiveTool(this.toolType, false, _readOnly_);}'}},
+ { title: "Segment", toolTip: "Erase between intersections",btnType:ButtonType.ToggleButton,icon:"xmark", toolType:InkEraserTool.Segment, ignoreClick: true, scripts: {onClick: '{ return setActiveTool(this.toolType, false, _readOnly_);}'}},
+ { title: "Area", toolTip: "Erase like a pencil", btnType: ButtonType.ToggleButton, icon: "circle-xmark",toolType:InkEraserTool.Radius, ignoreClick: true, scripts: {onClick: '{ return setActiveTool(this.toolType, false, _readOnly_);}'}},
]},
- { title: "Eraser Width", toolTip: "Eraser Width", btnType: ButtonType.NumberSliderButton, toolType: "eraserWidth", ignoreClick: true, scripts: {script: '{ return setInkProperty(this.toolType, value, _readOnly_);}'}, numBtnMin: 1, funcs: {hidden:"NotRadiusEraser()"}},
- { title: "Circle", toolTip: "Circle (double tap to lock mode)", btnType: ButtonType.ToggleButton, icon: "circle", toolType: Gestures.Circle, scripts: {onClick:`{ return setActiveTool(this.toolType, false, _readOnly_);}`, onDoubleClick:`{ return setActiveTool(this.toolType, true, _readOnly_);}`} },
- { title: "Square", toolTip: "Square (double tap to lock mode)", btnType: ButtonType.ToggleButton, icon: "square", toolType: Gestures.Rectangle, scripts: {onClick:`{ return setActiveTool(this.toolType, false, _readOnly_);}`, onDoubleClick:`{ return setActiveTool(this.toolType, true, _readOnly_);}`} },
- { title: "Line", toolTip: "Line (double tap to lock mode)", btnType: ButtonType.ToggleButton, icon: "minus", toolType: Gestures.Line, scripts: {onClick:`{ return setActiveTool(this.toolType, false, _readOnly_);}`, onDoubleClick:`{ return setActiveTool(this.toolType, true, _readOnly_);}`} },
- { title: "Mask", toolTip: "Mask", btnType: ButtonType.ToggleButton, icon: "user-circle",toolType: "inkMask", scripts: {onClick:'{ return setInkProperty(this.toolType, value, _readOnly_);}'}, funcs: {hidden:"IsNoviceMode()" } },
- { title: "Labels", toolTip: "Labels", btnType: ButtonType.ToggleButton, icon: "text-width", toolType: "labels", scripts: {onClick:'{ return setInkProperty(this.toolType, value, _readOnly_);}'}, },
- { title: "Width", toolTip: "Stroke width", btnType: ButtonType.NumberSliderButton, toolType: "strokeWidth", ignoreClick: true, scripts: {script: '{ return setInkProperty(this.toolType, value, _readOnly_);}'}, numBtnMin: 1},
- { title: "Ink", toolTip: "Stroke color", btnType: ButtonType.ColorButton, icon: "pen", toolType: "strokeColor", ignoreClick: true, scripts: {script: '{ return setInkProperty(this.toolType, value, _readOnly_);}'} },
- { title: "Smart Draw", toolTip: "Draw with GPT", btnType: ButtonType.ToggleButton, icon: "user-pen", toolType: "smartdraw", scripts: {onClick:'{ return setActiveTool(this.toolType, false, _readOnly_);}'}, funcs: {hidden: "IsNoviceMode()"}},
+ { title: " Size", toolTip: "Size of area pencil eraser", btnType: ButtonType.NumberSliderButton, toolType: InkProperty.EraserWidth,ignoreClick: true, scripts: {script: '{ return setInkProperty(this.toolType, value, _readOnly_);}'}, funcs: {hidden:"NotRadiusEraser()"}, numBtnMin: 1, linearBtnWidth:40},
+ { title: "Mask", toolTip: "Make Stroke a Stencil Mask", btnType: ButtonType.ToggleButton, icon: "user-circle", toolType: InkProperty.Mask, scripts: {onClick:'{ return setInkProperty(this.toolType, value, _readOnly_);}'}, funcs: {hidden:"IsNoviceMode()" } },
+ { title: "Labels", toolTip: "Show Labels Inside Shapes", btnType: ButtonType.ToggleButton, icon: "text-width", toolType: InkProperty.Labels, scripts: {onClick:'{ return setInkProperty(this.toolType, value, _readOnly_);}'}},
+ { title: "Smart Draw", toolTip: "Draw with AI", btnType: ButtonType.ToggleButton, icon: "user-pen", toolType: InkTool.SmartDraw, scripts: {onClick:'{ return setActiveTool(this.toolType, false, _readOnly_);}'}, funcs: {hidden: "IsNoviceMode()"}},
];
}
@@ -809,25 +832,24 @@ pie title Minerals in my tap water
CollectionViewType.Masonry, CollectionViewType.Multicolumn, CollectionViewType.Multirow, CollectionViewType.Linear,
CollectionViewType.Map, CollectionViewType.NoteTaking, CollectionViewType.Schema, CollectionViewType.Stacking,
CollectionViewType.Calendar, CollectionViewType.Grid, CollectionViewType.Tree, CollectionViewType.Time, ]),
- title: "Perspective", toolTip: "View", btnType: ButtonType.DropdownList, ignoreClick: true, width: 100, scripts: { script: '{ return setView(value, _readOnly_); }'}},
- { title: "Pin", icon: "map-pin", toolTip: "Pin View to Trail", btnType: ButtonType.ClickButton, expertMode: false, width: 30, scripts: { onClick: 'pinWithView(altKey)'}, funcs: {hidden: "IsNoneSelected()"}},
- { title: "Header", icon: "heading", toolTip: "Doc Titlebar Color", btnType: ButtonType.ColorButton, expertMode: false, ignoreClick: true, scripts: { script: 'return setHeaderColor(value, _readOnly_)'} },
- { title: "Template",icon: "scroll", toolTip: "Default Note Template",btnType: ButtonType.ToggleButton, expertMode: false, toolType:DocumentType.RTF, scripts: { onClick: '{ return setDefaultTemplate(_readOnly_); }'} },
- { title: "Fill", icon: "fill-drip", toolTip: "Fill/Background Color",btnType: ButtonType.ColorButton, expertMode: false, ignoreClick: true, width: 30, scripts: { script: 'return setBackgroundColor(value, _readOnly_)'}, funcs: {hidden: "IsNoneSelected()"}}, // Only when a document is selected
- { title: "Overlay", icon: "layer-group", toolTip: "Overlay", btnType: ButtonType.ToggleButton, expertMode: true, toolType:CollectionViewType.Freeform, funcs: {hidden: '!SelectedDocType(this.toolType, this.expertMode, true)'}, scripts: { onClick: '{ return toggleOverlay(_readOnly_); }'}}, // Only when floating document is selected in freeform
- { title: "Back", icon: "chevron-left", toolTip: "Prev Animation Frame", btnType: ButtonType.ClickButton, expertMode: true, toolType:CollectionViewType.Freeform, funcs: {hidden: '!SelectedDocType(this.toolType, this.expertMode)'}, width: 30, scripts: { onClick: 'prevKeyFrame(_readOnly_)'}},
- { title: "Num", icon:"", toolTip: "Frame # (click to toggle edit mode)",btnType: ButtonType.TextButton, expertMode: true, toolType:CollectionViewType.Freeform, funcs: {hidden: '!SelectedDocType(this.toolType, this.expertMode)', buttonText: 'selectedDocs()?.lastElement()?.currentFrame?.toString()'}, width: 20, scripts: { onClick: '{ return curKeyFrame(_readOnly_);}'}},
- { title: "Fwd", icon: "chevron-right", toolTip: "Next Animation Frame", btnType: ButtonType.ClickButton, expertMode: true, toolType:CollectionViewType.Freeform, funcs: {hidden: '!SelectedDocType(this.toolType, this.expertMode)'}, width: 30, scripts: { onClick: 'nextKeyFrame(_readOnly_)'}},
-
- { title: "Filter", icon: "=", toolTip: "Filter cards by tags", subMenu: CurrentUserUtils.tagGroupTools(),ignoreClick:true, toolType:DocumentType.COL, funcs: {hidden: '!SelectedDocType(this.toolType, this.expertMode)'}, btnType: ButtonType.MultiToggleButton, width: 30, backgroundColor: doc.userVariantColor as string},
+ title: "Perspective", toolTip: "View", btnType: ButtonType.DropdownList, ignoreClick: true, width: 100, scripts: { script: '{ return setView(value, shiftKey, _readOnly_); }'}},
+ { title: "Pin", icon: "map-pin", toolTip: "Pin View to Trail", btnType: ButtonType.ClickButton, expertMode: false, width: 30, scripts: { onClick: 'pinWithView(altKey)'}, funcs: {hidden: "IsNoneSelected()"}},
+ { title: "Header", icon: "heading", toolTip: "Doc Titlebar Color", btnType: ButtonType.ColorButton, expertMode: false, ignoreClick: true, scripts: { script: 'return setHeaderColor(value, _readOnly_)'} },
+ { title: "Template",icon: "scroll", toolTip: "Default Note Template",btnType: ButtonType.ToggleButton, expertMode: false, toolType:DocumentType.RTF, scripts: { onClick: '{ return setDefaultTemplate(_readOnly_); }'} },
+ { title: "Fill", icon: "fill-drip", toolTip: "Fill/Background Color",btnType: ButtonType.ColorButton, expertMode: false, ignoreClick: true, width: 30, scripts: { script: 'return setBackgroundColor(value, _readOnly_)'} }, // Only when a document is selected
+ { title: "Overlay", icon: "layer-group", toolTip: "Overlay", btnType: ButtonType.ToggleButton, expertMode: true, toolType:CollectionViewType.Freeform, funcs: {hidden: '!SelectedDocType(this.toolType, this.expertMode, true)'}, scripts: { onClick: '{ return toggleOverlay(_readOnly_); }'}}, // Only when floating document is selected in freeform
+ { title: "Back", icon: "chevron-left", toolTip: "Prev Animation Frame", btnType: ButtonType.ClickButton, expertMode: true, toolType:CollectionViewType.Freeform, funcs: {hidden: '!SelectedDocType(this.toolType, this.expertMode)'}, width: 30, scripts: { onClick: 'prevKeyFrame(_readOnly_)'}},
+ { title: "Num", icon:"", toolTip: "Frame # (click to toggle edit mode)",btnType: ButtonType.TextButton, expertMode: true, toolType:CollectionViewType.Freeform, funcs: {hidden: '!SelectedDocType(this.toolType, this.expertMode)', buttonText: 'selectedDocs()?.lastElement()?.currentFrame?.toString()'}, width: 20, scripts: { onClick: '{ return curKeyFrame(_readOnly_);}'}},
+ { title: "Fwd", icon: "chevron-right", toolTip: "Next Animation Frame", btnType: ButtonType.ClickButton, expertMode: true, toolType:CollectionViewType.Freeform, funcs: {hidden: '!SelectedDocType(this.toolType, this.expertMode)'}, width: 30, scripts: { onClick: 'nextKeyFrame(_readOnly_)'}},
+ { title: "Chat", icon:"lightbulb", toolTip: "Toggle Chat Assistant",btnType: ButtonType.ToggleButton, expertMode: false, toolType:"toggle-chat", funcs: {}, width: 30, scripts: { onClick: '{ return showFreeform(this.toolType, _readOnly_);}'} },
+ { title: "Filter", icon: "=", toolTip: "Filter cards by tags", subMenu: CurrentUserUtils.filterTools(), ignoreClick:true, toolType:DocumentType.COL, funcs: {hidden: '!SelectedDocType(this.toolType, this.expertMode)'}, btnType: ButtonType.MultiToggleButton, width: 30, backgroundColor: doc.userVariantColor as string},
+ { title: "Sort", icon: "Sort", toolTip: "Sort Documents", subMenu: CurrentUserUtils.sortTools(), expertMode: false, toolType:DocumentType.COL, funcs: {hidden: `!SelectedDocType(this.toolType, this.expertMode)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, // Always available
{ title: "Text", icon: "Text", toolTip: "Text functions", subMenu: CurrentUserUtils.textTools(), expertMode: false, toolType:DocumentType.RTF, funcs: { linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, // Always available
{ title: "Ink", icon: "Ink", toolTip: "Ink functions", subMenu: CurrentUserUtils.inkTools(), expertMode: false, toolType:DocumentType.INK, funcs: {hidden: `IsExploreMode()`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`}, scripts: { onClick: 'setInkToolDefaults()'} }, // Always available
{ title: "Doc", icon: "Doc", toolTip: "Freeform Doc tools", subMenu: CurrentUserUtils.freeTools(), expertMode: false, toolType:CollectionViewType.Freeform, funcs: {hidden: `!SelectedDocType(this.toolType, this.expertMode, true)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, // Always available
- { title: "View", icon: "View", toolTip: "View tools", subMenu: CurrentUserUtils.viewTools(), expertMode: false, toolType:CollectionViewType.Freeform, funcs: {hidden: `!SelectedDocType(this.toolType, this.expertMode)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, // Always available
+ { title: "View", icon: "View", toolTip: "View tools", subMenu: CurrentUserUtils.viewTools(), expertMode: false, toolType:DocumentType.COL, funcs: {hidden: `!SelectedDocType(this.toolType, this.expertMode)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, // Always available
{ title: "Stack", icon: "View", toolTip: "Stacking tools", subMenu: CurrentUserUtils.stackTools(), expertMode: false, toolType:CollectionViewType.Stacking, funcs: {hidden: `!SelectedDocType(this.toolType, this.expertMode)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, // Always available
- { title: "Card", icon: "Card", toolTip: "Card View Tools", subMenu: CurrentUserUtils.cardTools(), expertMode: false, toolType:CollectionViewType.Card, funcs: {hidden: `!SelectedDocType(this.toolType, this.expertMode)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, // Always available
- // { title: "Create", icon: "Create", toolTip: "Assign card labels", subMenu: CurrentUserUtils.labelTools(), expertMode: false, toolType:CollectionViewType.Card, funcs: {hidden: `!SelectedDocType(this.toolType, this.expertMode)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, // Always available
{ title: "Web", icon: "Web", toolTip: "Web functions", subMenu: CurrentUserUtils.webTools(), expertMode: false, toolType:DocumentType.WEB, funcs: {hidden: `!SelectedDocType(this.toolType, this.expertMode)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, // Only when Web is selected
{ title: "Video", icon: "Video", toolTip: "Video functions", subMenu: CurrentUserUtils.videoTools(), expertMode: false, toolType:DocumentType.VID, funcs: {hidden: `!SelectedDocType(this.toolType, this.expertMode)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, // Only when video is selected
{ title: "Image", icon: "Image", toolTip: "Image functions", subMenu: CurrentUserUtils.imageTools(), expertMode: false, toolType:DocumentType.IMG, funcs: {hidden: `!SelectedDocType(this.toolType, this.expertMode)`, linearView_IsOpen: `SelectedDocType(this.toolType, this.expertMode)`} }, // Only when image is selected
@@ -862,10 +884,10 @@ pie title Minerals in my tap water
}
// linear view
const reqdSubMenuOpts = { ...OmitKeys(params, ["scripts", "funcs", "subMenu"]).omit, undoIgnoreFields: new List<string>(['width', "linearView_IsOpen"]),
- childDontRegisterViews: true, flexGap: 0, _height: 30, ignoreClick: !params.scripts?.onClick,
+ childDontRegisterViews: true, flexGap: 0, _height: 30, _width: 30, ignoreClick: !params.scripts?.onClick,
linearView_SubMenu: true, linearView_Expandable: true, embedContainer: menuDoc};
- const items = (menutBtn?:Doc) => !menutBtn ? [] : subMenu.map(sub => this.setupContextMenuBtn(sub, menutBtn) );
+ const items = (menuBtn?:Doc) => !menuBtn ? [] : subMenu.map(sub => this.setupContextMenuBtn(sub, menuBtn) );
const creator = params.btnType === ButtonType.MultiToggleButton ? this.multiToggleList : this.linearButtonList;
const btnDoc = DocUtils.AssignScripts( DocUtils.AssignDocField(menuDoc, StrCast(params.title),
(opts) => creator(opts, items(menuBtnDoc)), reqdSubMenuOpts, items(menuBtnDoc)), params.scripts, params.funcs);
@@ -986,15 +1008,23 @@ pie title Minerals in my tap water
Doc.noviceMode ?? (Doc.noviceMode = true);
doc._showLabel ?? (doc._showLabel = true);
doc.textAlign ?? (doc.textAlign = "left");
+ doc.textBackgroundColor ?? (doc.textBackgroundColor = Colors.LIGHT_GRAY);
doc.activeTool = InkTool.None;
doc.openInkInLightbox ?? (doc.openInkInLightbox = false);
- doc.activeInkHideTextLabels ?? (doc.activeInkHideTextLabels = false);
- doc.activeInkColor ?? (doc.activeInkColor = "rgb(0, 0, 0)");
- doc.activeInkWidth ?? (doc.activeInkWidth = 1);
- doc.activeInkBezier ?? (doc.activeInkBezier = "0");
- doc.activeFillColor ?? (doc.activeFillColor = "");
- doc.activeArrowStart ?? (doc.activeArrowStart = "");
- doc.activeArrowEnd ?? (doc.activeArrowEnd = "");
+ doc.activeHideTextLabels ?? (doc.activeHideTextLabels = false);
+ doc[`active${InkInkTool.Pen}Color`] ?? (doc[`active${InkInkTool.Pen}Color`] = "rgb(0, 0, 0)");
+ doc[`active${InkInkTool.Pen}Width`] ?? (doc[`active${InkInkTool.Pen}Width`] = 2);
+ doc[`active${InkInkTool.Pen}Bezier`] ?? (doc[`active${InkInkTool.Pen}Bezier`] = "0");
+ doc[`active${InkInkTool.Write}Color`] ?? (doc[`active${InkInkTool.Write}Color`] = "rgb(255, 0, 0)");
+ doc[`active${InkInkTool.Write}Width`] ?? (doc[`active${InkInkTool.Write}Width`] = 1);
+ doc[`active${InkInkTool.Write}Bezier`] ?? (doc[`active${InkInkTool.Write}Bezier`] = "0");
+ doc[`active${InkInkTool.Highlight}Color`] ?? (doc[`active${InkInkTool.Highlight}Color`] = 'transparent');
+ doc[`active${InkInkTool.Highlight}Width`] ?? (doc[`active${InkInkTool.Highlight}Width`] = 20);
+ doc[`active${InkInkTool.Highlight}Bezier`] ?? (doc[`active${InkInkTool.Highlight}Bezier`] = "0");
+ doc[`active${InkInkTool.Highlight}Fill`] ?? (doc[`active${InkInkTool.Highlight}Fill`] = "rgba(0, 255, 255, 0.4)");
+ doc.activeInkTool ?? (doc.activeInkTool = InkInkTool.Pen);
+ doc.activeEraserTool ?? (doc.activeEraserTool = InkEraserTool.Stroke);
+ doc.activeEraserWidth ?? (doc.activeEraserWidth = 20);
doc.activeDash ?? (doc.activeDash === "0");
doc.fontSize ?? (doc.fontSize = "12px");
doc.fontFamily ?? (doc.fontFamily = "Arial");
@@ -1129,7 +1159,9 @@ pie title Minerals in my tap water
}
// eslint-disable-next-line prefer-arrow-callback
-ScriptingGlobals.add(function NotRadiusEraser() { return Doc.ActiveTool !== InkTool.RadiusEraser; }, "is the active tool anything but the radius eraser");
+ScriptingGlobals.add(function activeInkTool() { return Doc.ActiveTool=== InkTool.Ink || DocumentView.Selected().some(dv => dv.layoutDoc.layout_isSvg); }, "is a pen tool or an ink stroke active");
+// eslint-disable-next-line prefer-arrow-callback
+ScriptingGlobals.add(function NotRadiusEraser() { return Doc.ActiveTool !== InkTool.Eraser || Doc.ActiveEraser !== InkEraserTool.Radius; }, "is the active tool anything but the radius eraser");
// eslint-disable-next-line prefer-arrow-callback
ScriptingGlobals.add(function MySharedDocs() { return Doc.MySharedDocs; }, "document containing all shared Docs");
// eslint-disable-next-line prefer-arrow-callback
diff --git a/src/client/util/DictationManager.ts b/src/client/util/DictationManager.ts
index 831afe538..897366757 100644
--- a/src/client/util/DictationManager.ts
+++ b/src/client/util/DictationManager.ts
@@ -71,7 +71,6 @@ export namespace DictationManager {
let current: string | undefined;
let sessionResults: string[] = [];
- // eslint-disable-next-line new-cap
const recognizer: Opt<SpeechRecognition> = webkitSpeechRecognition ? new webkitSpeechRecognition() : undefined;
export type InterimResultHandler = (results: string) => void;
@@ -257,7 +256,6 @@ export namespace DictationManager {
if (entry) {
let success = false;
const { restrictTo } = entry;
- // eslint-disable-next-line no-restricted-syntax
for (const target of targets) {
if (!restrictTo || validate(target, restrictTo)) {
// eslint-disable-next-line no-await-in-loop
@@ -268,7 +266,6 @@ export namespace DictationManager {
return success;
}
- // eslint-disable-next-line no-restricted-syntax
for (const depEntry of Dependent) {
const regex = depEntry.expression;
const matches = regex.exec(phrase);
@@ -276,7 +273,6 @@ export namespace DictationManager {
if (matches !== null) {
let success = false;
const { restrictTo } = depEntry;
- // eslint-disable-next-line no-restricted-syntax
for (const target of targets) {
if (!restrictTo || validate(target, restrictTo)) {
// eslint-disable-next-line no-await-in-loop
@@ -307,7 +303,6 @@ export namespace DictationManager {
};
const validate = (target: DocumentView, types: DocumentType[]) => {
- // eslint-disable-next-line no-restricted-syntax
for (const type of types) {
if (tryCast(target, type)) {
return true;
diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts
index 4ab2e8d05..acb35f7eb 100644
--- a/src/client/util/DocumentManager.ts
+++ b/src/client/util/DocumentManager.ts
@@ -8,7 +8,7 @@ import { Cast, DocCast, NumCast, StrCast } from '../../fields/Types';
import { AudioField } from '../../fields/URLField';
import { CollectionViewType } from '../documents/DocumentTypes';
import { DocumentView, DocumentViewInternal } from '../views/nodes/DocumentView';
-import { FocusViewOptions } from '../views/nodes/FocusViewOptions';
+import { FocusEffectDelay, FocusViewOptions } from '../views/nodes/FocusViewOptions';
import { OpenWhere } from '../views/nodes/OpenWhere';
import { PresBox } from '../views/nodes/trails';
@@ -256,7 +256,11 @@ export class DocumentManager {
Doc.RemoveDocFromList(Doc.MyRecentlyClosed, undefined, targetDoc);
const docContextPath = DocumentManager.GetContextPath(targetDoc, true);
if (docContextPath.some(doc => doc.hidden)) options.toggleTarget = false;
- if (DocumentView.activateTabView(docContextPath[0])) options.toggleTarget = false;
+ let activatedTab = false;
+ if (DocumentView.activateTabView(docContextPath[0])) {
+ options.toggleTarget = false;
+ activatedTab = true;
+ }
const rootContextView =
docContextPath.length &&
@@ -268,7 +272,7 @@ export class DocumentManager {
return;
}
options.didMove = true;
- (!DocumentView.LightboxDoc() && docContextPath.some(doc => DocumentView.activateTabView(doc))) || DocumentViewInternal.addDocTabFunc(docContextPath[0], options.openLocation ?? OpenWhere.addRight);
+ (!DocumentView.LightboxDoc() && (activatedTab || docContextPath.some(doc => DocumentView.activateTabView(doc)))) || DocumentViewInternal.addDocTabFunc(docContextPath[0], options.openLocation ?? OpenWhere.addRight);
this.AddViewRenderedCb(docContextPath[0], dv => res(dv));
}));
if (options.openLocation?.includes(OpenWhere.lightbox)) {
@@ -348,21 +352,18 @@ export class DocumentManager {
// if there's an options.effect, it will be handled from linkFollowHighlight. We delay the start of
// the highlight so that the target document can be somewhat centered so that the effect/highlight will be seen
// bcz: should this delay be an options parameter?
- setTimeout(
- () => {
- Doc.linkFollowHighlight(viewSpec ? [docView.Document, viewSpec] : docView.Document, undefined, options.effect);
- if (options.zoomTextSelections && Doc.IsUnhighlightTimerSet() && contextView && targetDoc.text_html) {
- // if the docView is a text anchor, the contextView is the PDF/Web/Text doc
- contextView.setTextHtmlOverlay(StrCast(targetDoc.text_html), options.effect);
- DocumentManager._overlayViews.add(contextView);
- }
- Doc.AddUnHighlightWatcher(() => {
- docView.Document[Animation] = undefined;
- DocumentManager.removeOverlayViews();
- });
- },
- (options.zoomTime ?? 0) * 0.5
- );
+ setTimeout(() => {
+ Doc.linkFollowHighlight(viewSpec ? [docView.Document, viewSpec] : docView.Document, undefined, options.effect);
+ if (options.zoomTextSelections && Doc.IsUnhighlightTimerSet() && contextView && targetDoc.text_html) {
+ // if the docView is a text anchor, the contextView is the PDF/Web/Text doc
+ contextView.setTextHtmlOverlay(StrCast(targetDoc.text_html), options.effect);
+ DocumentManager._overlayViews.add(contextView);
+ }
+ Doc.AddUnHighlightWatcher(() => {
+ docView.Document[Animation] = undefined;
+ DocumentManager.removeOverlayViews();
+ });
+ }, FocusEffectDelay(options));
if (options.playMedia) docView.ComponentView?.playFrom?.(NumCast(docView.Document._layout_currentTimecode));
if (options.playAudio) DocumentManager.playAudioAnno(docView.Document);
if (options.toggleTarget && (!options.didMove || docView.Document.hidden)) docView.Document.hidden = !docView.Document.hidden;
diff --git a/src/client/util/GroupManager.tsx b/src/client/util/GroupManager.tsx
index 9d0817a06..1ec85c9d9 100644
--- a/src/client/util/GroupManager.tsx
+++ b/src/client/util/GroupManager.tsx
@@ -1,5 +1,5 @@
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { Button, IconButton, Size, Type } from 'browndash-components';
+import { Button, IconButton, Size, Type } from '@dash/components';
import { action, computed, makeObservable, observable, runInAction } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
diff --git a/src/client/util/GroupMemberView.tsx b/src/client/util/GroupMemberView.tsx
index 88d73d742..cfeaf02d7 100644
--- a/src/client/util/GroupMemberView.tsx
+++ b/src/client/util/GroupMemberView.tsx
@@ -1,5 +1,5 @@
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { Button, IconButton, Size, Type } from 'browndash-components';
+import { Button, IconButton, Size, Type } from '@dash/components';
import { action, observable } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
diff --git a/src/client/util/InteractionUtils.tsx b/src/client/util/InteractionUtils.tsx
index 4231c2ca8..ca1cb8014 100644
--- a/src/client/util/InteractionUtils.tsx
+++ b/src/client/util/InteractionUtils.tsx
@@ -109,7 +109,7 @@ export namespace InteractionUtils {
dash: string | undefined,
scalexIn: number,
scaleyIn: number,
- shape: Gestures,
+ shape: Gestures | undefined,
pevents: Property.PointerEvents,
opacity: number,
nodefs: boolean,
@@ -136,7 +136,7 @@ export namespace InteractionUtils {
const arrowLengthFactor = 5 * (markerScale || 0.5);
const arrowNotchFactor = 2 * (markerScale || 0.5);
return (
- <svg fill={color} style={{ transition: 'inherit' }} onPointerDown={downHdlr}>
+ <svg fill={color || 'transparent'} style={{ transition: 'inherit' }} onPointerDown={downHdlr}>
{' '}
{/* setting the svg fill sets the arrowStart fill */}
{nodefs ? null : (
@@ -186,7 +186,7 @@ export namespace InteractionUtils {
opacity: 1.0,
// opacity: strokeWidth !== width ? 0.5 : undefined,
pointerEvents: pevents === 'all' ? 'visiblePainted' : pevents,
- stroke: color ?? 'rgb(0, 0, 0)',
+ stroke: (color ?? 'rgb(0, 0, 0)') || 'transparent',
strokeWidth,
strokeLinecap: strokeLineCap,
strokeDasharray: dashArray,
diff --git a/src/client/util/LinkFollower.ts b/src/client/util/LinkFollower.ts
index 0a3a0ba49..0e67dcfaa 100644
--- a/src/client/util/LinkFollower.ts
+++ b/src/client/util/LinkFollower.ts
@@ -113,12 +113,10 @@ export class LinkFollower {
}
const moveTo = [NumCast(sourceDoc.x) + NumCast(sourceDoc.followLinkXoffset), NumCast(sourceDoc.y) + NumCast(sourceDoc.followLinkYoffset)];
if (srcAnchor.followLinkXoffset !== undefined && moveTo[0] !== target.x) {
- // eslint-disable-next-line prefer-destructuring
target.x = moveTo[0];
movedTarget = true;
}
if (srcAnchor.followLinkYoffset !== undefined && moveTo[1] !== target.y) {
- // eslint-disable-next-line prefer-destructuring
target.y = moveTo[1];
movedTarget = true;
}
diff --git a/src/client/util/SelectionManager.ts b/src/client/util/SelectionManager.ts
index 1ab84421c..a1f2849cd 100644
--- a/src/client/util/SelectionManager.ts
+++ b/src/client/util/SelectionManager.ts
@@ -88,7 +88,8 @@ ScriptingGlobals.add(function SelectedDocType(type: string, expertMode: boolean,
return DocumentView.Selected().lastElement()?._props.renderDepth === 0;
}
const selected = (sel => (checkContext ? DocCast(sel?.embedContainer) : sel))(DocumentView.SelectedSchemaDoc() ?? SelectionManager.Docs().lastElement());
- return selected?.type === type || selected?.type_collection === type || !type;
+ const matchOverlayFreeform = type === CollectionViewType.Freeform && DocumentView.Selected().lastElement()?.ComponentView?.annotationKey;
+ return matchOverlayFreeform || selected?.type === type || selected?.type_collection === type || !type;
});
// eslint-disable-next-line prefer-arrow-callback
ScriptingGlobals.add(function deselectAll() {
diff --git a/src/client/util/SettingsManager.tsx b/src/client/util/SettingsManager.tsx
index 9200d68db..5d041f7b4 100644
--- a/src/client/util/SettingsManager.tsx
+++ b/src/client/util/SettingsManager.tsx
@@ -1,5 +1,5 @@
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { Button, ColorPicker, Dropdown, DropdownType, EditableText, Group, NumberDropdown, Size, Toggle, ToggleType, Type } from 'browndash-components';
+import { Button, ColorPicker, Colors, Dropdown, DropdownType, EditableText, Group, NumberDropdown, Size, Toggle, ToggleType, Type } from '@dash/components';
import { action, computed, makeObservable, observable, reaction, runInAction } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
@@ -45,7 +45,6 @@ export class SettingsManager extends React.Component<object> {
public closeMgr = action(() => {
this._isOpen = false;
});
- // eslint-disable-next-line react/no-unused-class-component-methods
public openMgr = action(() => {
this._isOpen = true;
});
@@ -269,9 +268,9 @@ export class SettingsManager extends React.Component<object> {
formLabelPlacement="right"
toggleType={ToggleType.SWITCH}
onClick={() => {
- Doc.UserDoc().activeInkHideTextLabels = !Doc.UserDoc().activeInkHideTextLabels;
+ Doc.UserDoc().activeHideTextLabels = !Doc.UserDoc().activeHideTextLabels;
}}
- toggleStatus={BoolCast(Doc.UserDoc().activeInkHideTextLabels)}
+ toggleStatus={BoolCast(Doc.UserDoc().activeHideTextLabels)}
size={Size.XSMALL}
color={SettingsManager.userColor}
/>
@@ -354,6 +353,27 @@ export class SettingsManager extends React.Component<object> {
Doc.UserDoc().fontSize = val + 'px';
}}
/>
+ <ColorPicker
+ color={SettingsManager.userColor}
+ type={Type.PRIM}
+ defaultPickerType="Classic"
+ selectedColor={StrCast(Doc.UserDoc().textBackgroundColor, Colors.LIGHT_GRAY)}
+ background={SnappingManager.userBackgroundColor}
+ icon={<FontAwesomeIcon icon="palette" size="lg" />}
+ tooltip="default text background color"
+ label="background"
+ setSelectedColor={value => {
+ Doc.UserDoc().textBackgroundColor = value;
+ // if (!this.colorBatch) this.colorBatch = UndoManager.StartBatch(`Set ${tooltip} color`);
+ // this.colorScript?.script.run({ this: this.Document, value: value, _readOnly_: false });
+ }}
+ setFinalColor={value => {
+ Doc.UserDoc().textBackgroundColor = value;
+ // this.colorScript?.script.run({ this: this.Document, value: value, _readOnly_: false });
+ // this.colorBatch?.end();
+ // this.colorBatch = undefined;
+ }}
+ />
<Dropdown
items={fontFamilies.map(val => ({
text: val,
diff --git a/src/client/util/SharingManager.tsx b/src/client/util/SharingManager.tsx
index 117d7935e..efc8e79a6 100644
--- a/src/client/util/SharingManager.tsx
+++ b/src/client/util/SharingManager.tsx
@@ -1,5 +1,5 @@
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { Button, IconButton, Size, Type } from 'browndash-components';
+import { Button, IconButton, Size, Type } from '@dash/components';
import { concat, intersection } from 'lodash';
import { action, computed, makeObservable, observable, runInAction } from 'mobx';
import { observer } from 'mobx-react';
diff --git a/src/client/util/SnappingManager.ts b/src/client/util/SnappingManager.ts
index 5f6c7d9ac..2a150dc5a 100644
--- a/src/client/util/SnappingManager.ts
+++ b/src/client/util/SnappingManager.ts
@@ -1,4 +1,5 @@
import { observable, action, runInAction, makeObservable } from 'mobx';
+import { Gestures } from '../../pen-gestures/GestureTypes';
export enum freeformScrollMode {
Pan = 'pan',
@@ -29,6 +30,8 @@ export class SnappingManager {
@observable _propertyWid: number = 0;
@observable _printToConsole: boolean = false;
@observable _hideDecorations: boolean = false;
+ @observable _keepGestureMode: boolean = false; // for whether primitive selection enters a one-shot or persistent mode
+ @observable _inkShape: Gestures | undefined = undefined;
private constructor() {
SnappingManager._manager = this;
@@ -61,6 +64,8 @@ export class SnappingManager {
public static get PropertiesWidth(){ return this.Instance._propertyWid; } // prettier-ignore
public static get PrintToConsole() { return this.Instance._printToConsole; } // prettier-ignore
public static get HideDecorations(){ return this.Instance._hideDecorations; } // prettier-ignore
+ public static get KeepGestureMode(){ return this.Instance._keepGestureMode; } // prettier-ignore
+ public static get InkShape() { return this.Instance._inkShape; } // prettier-ignore
public static SetLongPress = (press: boolean) => runInAction(() => {this.Instance._longPress = press}); // prettier-ignore
public static SetShiftKey = (down: boolean) => runInAction(() => {this.Instance._shiftKey = down}); // prettier-ignore
@@ -78,6 +83,8 @@ export class SnappingManager {
public static SetPropertiesWidth= (wid:number) =>runInAction(() => {this.Instance._propertyWid = wid}); // prettier-ignore
public static SetPrintToConsole = (state:boolean) =>runInAction(() => {this.Instance._printToConsole = state}); // prettier-ignore
public static SetHideDecorations= (state:boolean) =>runInAction(() => {this.Instance._hideDecorations = state}); // prettier-ignore
+ public static SetKeepGestureMode= (state:boolean) =>runInAction(() => {this.Instance._keepGestureMode = state}); // prettier-ignore
+ public static SetInkShape = (shape?:Gestures)=>runInAction(() => {this.Instance._inkShape = shape}); // prettier-ignore
public static userColor: string | undefined;
public static userVariantColor: string | undefined;
diff --git a/src/client/util/bezierFit.ts b/src/client/util/bezierFit.ts
index 4aef28e6b..7ef370d48 100644
--- a/src/client/util/bezierFit.ts
+++ b/src/client/util/bezierFit.ts
@@ -691,8 +691,9 @@ export function SVGToBezier(name: SVGType, attributes: any): Point[] {
}
case 'path': {
const coordList: Point[] = [];
- const startPt = attributes.d.match(/M(-?\d+\.?\d*),(-?\d+\.?\d*)/);
- coordList.push({ X: parseInt(startPt[1]), Y: parseInt(startPt[2]) });
+ const [startX, startY] = attributes.d.match(/M(-?\d+\.?\d*),(-?\d+\.?\d*)/).slice(1);
+ const startPt = { X: parseInt(startX), Y: parseInt(startY) };
+ coordList.push(startPt);
const matches: RegExpMatchArray[] = Array.from(
attributes.d.matchAll(/Q(-?\d+\.?\d*),(-?\d+\.?\d*) (-?\d+\.?\d*),(-?\d+\.?\d*)|C(-?\d+\.?\d*),(-?\d+\.?\d*) (-?\d+\.?\d*),(-?\d+\.?\d*) (-?\d+\.?\d*),(-?\d+\.?\d*)|L(-?\d+\.?\d*),(-?\d+\.?\d*)/g)
);
@@ -719,10 +720,10 @@ export function SVGToBezier(name: SVGType, attributes: any): Point[] {
}
});
const hasZ = attributes.d.match(/Z/);
- if (hasZ) {
+ if (hasZ || attributes.fill) {
coordList.push(lastPt);
- coordList.push({ X: parseInt(startPt[1]), Y: parseInt(startPt[2]) });
- coordList.push({ X: parseInt(startPt[1]), Y: parseInt(startPt[2]) });
+ coordList.push(startPt);
+ coordList.push(startPt);
} else {
coordList.pop();
}
diff --git a/src/client/util/reportManager/ReportManager.tsx b/src/client/util/reportManager/ReportManager.tsx
index c969f9036..a6b5911f7 100644
--- a/src/client/util/reportManager/ReportManager.tsx
+++ b/src/client/util/reportManager/ReportManager.tsx
@@ -1,6 +1,6 @@
/* eslint-disable react/no-unused-class-component-methods */
import { Octokit } from '@octokit/core';
-import { Button, Dropdown, DropdownType, IconButton, Type } from 'browndash-components';
+import { Button, Dropdown, DropdownType, IconButton, Type } from '@dash/components';
import { action, makeObservable, observable } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';