+
- {!this.props.Document.linearView_Expandable ? null : menuOpener}
- {!this.layoutDoc.linearView_IsExpanded ? null : (
-
- {this.childLayoutPairs.map(pair => this.getDisplayDoc(pair.layout))}
-
- )}
+ {this.props.Document.linearView_Dropdown ?
+
Hello World!
+ :
+ <>
+ {!this.props.Document.linearView_Expandable ? null : menuOpener}
+ {!this.layoutDoc.linearView_IsOpen ? null : (
+
+ {this.childLayoutPairs.map(pair => this.getDisplayDoc(pair.layout))}
+
+ )}
+ >
+ }
+
);
diff --git a/src/client/views/global/globalScripts.ts b/src/client/views/global/globalScripts.ts
index 8f6d898fe..d22b6b4d9 100644
--- a/src/client/views/global/globalScripts.ts
+++ b/src/client/views/global/globalScripts.ts
@@ -66,19 +66,20 @@ ScriptingGlobals.add(function setBackgroundColor(color?: string, checkResult?: b
// toggle: Set overlay status of selected document
ScriptingGlobals.add(function setHeaderColor(color?: string, checkResult?: boolean) {
if (checkResult) {
- return Doc.SharingDoc().userColor;
+ return Doc.SharingDoc().headingColor;
}
- Doc.SharingDoc().userColor = undefined;
- Doc.GetProto(Doc.SharingDoc()).userColor = color;
+ Doc.SharingDoc().headingColor = undefined;
+ Doc.GetProto(Doc.SharingDoc()).headingColor = color;
Doc.UserDoc().layout_showTitle = color === 'transparent' ? undefined : StrCast(Doc.UserDoc().layout_showTitle, 'author_date');
});
// toggle: Set overlay status of selected document
ScriptingGlobals.add(function toggleOverlay(checkResult?: boolean) {
+ console.log(checkResult);
const selected = SelectionManager.Views().length ? SelectionManager.Views()[0] : undefined;
if (checkResult) {
- if (NumCast(selected?.Document.z) >= 1) return Colors.MEDIUM_BLUE;
- return 'transparent';
+ if (NumCast(selected?.Document.z) >= 1) return true;
+ return false;
}
selected ? selected.props.CollectionFreeFormDocumentView?.().float() : console.log('[FontIconBox.tsx] toggleOverlay failed');
});
@@ -88,45 +89,47 @@ ScriptingGlobals.add(function showFreeform(attr: 'flashcards' | 'grid' | 'snapli
// prettier-ignore
const map: Map<'flashcards' | 'grid' | 'snaplines' | 'clusters' | 'arrange'| 'viewAll', { waitForRender?: boolean, checkResult: (doc:Doc) => any; setDoc: (doc:Doc) => void;}> = new Map([
['grid', {
- checkResult: (doc:Doc) => doc._freeform_backgroundGrid,
+ checkResult: (doc:Doc) => BoolCast(doc._freeform_backgroundGrid, false),
setDoc: (doc:Doc) => doc._freeform_backgroundGrid = !doc._freeform_backgroundGrid,
}],
['snaplines', {
- checkResult: (doc:Doc) => doc._freeform_snapLines,
+ checkResult: (doc:Doc) => BoolCast(doc._freeform_snapLines, false),
setDoc: (doc:Doc) => doc._freeform_snapLines = !doc._freeform_snapLines,
}],
['viewAll', {
- checkResult: (doc:Doc) => doc._freeform_fitContentsToBox,
+ checkResult: (doc:Doc) => BoolCast(doc._freeform_fitContentsToBox, false),
setDoc: (doc:Doc) => doc._freeform_fitContentsToBox = !doc._freeform_fitContentsToBox,
}],
['clusters', {
waitForRender: true, // flags that undo batch should terminate after a re-render giving the script the chance to fire
- checkResult: (doc:Doc) => doc._freeform_useClusters,
+ checkResult: (doc:Doc) => BoolCast(doc._freeform_useClusters, false),
setDoc: (doc:Doc) => doc._freeform_useClusters = !doc._freeform_useClusters,
}],
['arrange', {
waitForRender: true, // flags that undo batch should terminate after a re-render giving the script the chance to fire
- checkResult: (doc:Doc) => doc._autoArrange,
+ checkResult: (doc:Doc) => BoolCast(doc._autoArrange, false),
setDoc: (doc:Doc) => doc._autoArrange = !doc._autoArrange,
}],
['flashcards', {
- checkResult: (doc:Doc) => Doc.UserDoc().defaultToFlashcards,
+ checkResult: (doc:Doc) => BoolCast(Doc.UserDoc().defaultToFlashcards, false),
setDoc: (doc:Doc) => Doc.UserDoc().defaultToFlashcards = !Doc.UserDoc().defaultToFlashcards,
}],
]);
if (checkResult) {
- return map.get(attr)?.checkResult(selected) ? Colors.MEDIUM_BLUE : 'transparent';
+ console.log(attr, map.get(attr)?.checkResult(selected))
+ return map.get(attr)?.checkResult(selected);
}
const batch = map.get(attr)?.waitForRender ? UndoManager.StartBatch('set freeform attribute') : { end: () => {} };
SelectionManager.Docs().map(dv => map.get(attr)?.setDoc(dv));
setTimeout(() => batch.end(), 100);
});
-ScriptingGlobals.add(function setFontAttr(attr: 'font' | 'fontColor' | 'highlight' | 'fontSize', value: any, checkResult?: boolean) {
+
+ScriptingGlobals.add(function setFontAttr(attr: 'font' | 'fontColor' | 'highlight' | 'fontSize' | 'alignment', value: any, checkResult?: boolean) {
const editorView = RichTextMenu.Instance?.TextView?.EditorView;
const selected = SelectionManager.Docs().lastElement();
// prettier-ignore
- const map: Map<'font'|'fontColor'|'highlight'|'fontSize', { checkResult: () => any; setDoc: () => void;}> = new Map([
+ const map: Map<'font'|'fontColor'|'highlight'|'fontSize'|'alignment', { checkResult: () => any; setDoc: () => void;}> = new Map([
['font', {
checkResult: () => RichTextMenu.Instance?.fontFamily,
setDoc: () => value && RichTextMenu.Instance.setFontFamily(value),
@@ -139,6 +142,10 @@ ScriptingGlobals.add(function setFontAttr(attr: 'font' | 'fontColor' | 'highligh
checkResult: () => RichTextMenu.Instance?.fontColor,
setDoc: () => value && RichTextMenu.Instance.setColor(value),
}],
+ ['alignment', {
+ checkResult: () => RichTextMenu.Instance.textAlign,
+ setDoc: () => value && editorView?.state ? RichTextMenu.Instance.align(editorView, editorView.dispatch, value):(Doc.UserDoc().textAlign = value),
+ }],
['fontSize', {
checkResult: () => RichTextMenu.Instance?.fontSize.replace('px', ''),
setDoc: () => {
@@ -157,6 +164,7 @@ ScriptingGlobals.add(function setFontAttr(attr: 'font' | 'fontColor' | 'highligh
type attrname = 'noAutoLink' | 'dictation' | 'bold' | 'italics' | 'underline' | 'left' | 'center' | 'right' | 'bullet' | 'decimal';
type attrfuncs = [attrname, { checkResult: () => boolean; toggle: () => any }];
+
ScriptingGlobals.add(function toggleCharStyle(charStyle: attrname, checkResult?: boolean) {
const textView = RichTextMenu.Instance?.TextView;
const editorView = textView?.EditorView;
@@ -182,7 +190,10 @@ ScriptingGlobals.add(function toggleCharStyle(charStyle: attrname, checkResult?:
toggle: editorView ? RichTextMenu.Instance.toggleUnderline : () => (Doc.UserDoc().textDecoration = Doc.UserDoc().textDecoration === 'underline' ? undefined : 'underline') }]]
const map = new Map(attrs.concat(alignments).concat(listings));
- if (checkResult) return map.get(charStyle)?.checkResult() ? Colors.MEDIUM_BLUE : 'transparent';
+ if (checkResult) {
+ console.log(charStyle, checkResult, map.get(charStyle)?.checkResult());
+ return map.get(charStyle)?.checkResult();
+ }
map.get(charStyle)?.toggle();
});
@@ -270,9 +281,9 @@ function setActiveTool(tool: InkTool | GestureUtils.Gestures, keepPrim: boolean,
if (checkResult) {
return (Doc.ActiveTool === tool && !GestureOverlay.Instance?.InkShape) || GestureOverlay.Instance?.InkShape === tool
? GestureOverlay.Instance?.KeepPrimitiveMode || ![GestureUtils.Gestures.Circle, GestureUtils.Gestures.Line, GestureUtils.Gestures.Rectangle].includes(tool as GestureUtils.Gestures)
- ? Colors.MEDIUM_BLUE
- : Colors.MEDIUM_BLUE_ALT
- : 'transparent';
+ ? true
+ : true
+ : false;
}
runInAction(() => {
if (GestureOverlay.Instance) {
@@ -308,7 +319,7 @@ ScriptingGlobals.add(function setInkProperty(option: 'inkMask' | 'fillColor' | '
// prettier-ignore
const map: Map<'inkMask' | 'fillColor' | 'strokeWidth' | 'strokeColor', { checkResult: () => any; setInk: (doc: Doc) => void; setMode: () => void }> = new Map([
['inkMask', {
- checkResult: () => ((selected?.type === DocumentType.INK ? BoolCast(selected.stroke_isInkMask) : ActiveIsInkMask()) ? Colors.MEDIUM_BLUE : 'transparent'),
+ checkResult: () => ((selected?.type === DocumentType.INK ? BoolCast(selected.stroke_isInkMask) : ActiveIsInkMask())),
setInk: (doc: Doc) => (doc.stroke_isInkMask = !doc.stroke_isInkMask),
setMode: () => selected?.type !== DocumentType.INK && SetActiveIsInkMask(!ActiveIsInkMask()),
}],
diff --git a/src/client/views/linking/LinkPopup.scss b/src/client/views/linking/LinkPopup.scss
index b20ad9476..4bfb4b0b9 100644
--- a/src/client/views/linking/LinkPopup.scss
+++ b/src/client/views/linking/LinkPopup.scss
@@ -4,7 +4,6 @@
top: 0;
height: 200px;
width: 200px;
- position: absolute;
// padding: 15px;
border-radius: 3px;
@@ -37,8 +36,4 @@
margin: auto;
}
}
-
- .searchBox-container {
- background: pink;
- }
}
diff --git a/src/client/views/linking/LinkPopup.tsx b/src/client/views/linking/LinkPopup.tsx
index 745efea08..6895c0746 100644
--- a/src/client/views/linking/LinkPopup.tsx
+++ b/src/client/views/linking/LinkPopup.tsx
@@ -14,7 +14,6 @@ import React = require('react');
import { OpenWhere } from '../nodes/DocumentView';
interface LinkPopupProps {
- showPopup: boolean;
linkFrom?: () => Doc | undefined;
linkCreateAnchor?: () => Doc | undefined;
linkCreated?: (link: Doc) => void;
@@ -44,10 +43,9 @@ export class LinkPopup extends React.Component
{
getPHeight = () => 500;
render() {
- const popupVisibility = this.props.showPopup ? 'block' : 'none';
const linkDoc = this.props.linkFrom ? this.props.linkFrom : undefined;
return (
-
+
{/*
this.makeLinkToURL(this.linkURL, "add:right")}
diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx
index e954d0484..7e8eef0a5 100644
--- a/src/client/views/nodes/DocumentContentsView.tsx
+++ b/src/client/views/nodes/DocumentContentsView.tsx
@@ -18,7 +18,7 @@ import { SearchBox } from '../search/SearchBox';
import { DashWebRTCVideo } from '../webcam/DashWebRTCVideo';
import { YoutubeBox } from './../../apis/youtube/YoutubeBox';
import { AudioBox } from './AudioBox';
-import { FontIconBox } from './button/FontIconBox';
+import { FontIconBox } from './FontIconBox/FontIconBox';
import { ColorBox } from './ColorBox';
import { ComparisonBox } from './ComparisonBox';
import { DataVizBox } from './DataVizBox/DataVizBox';
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 8a35ca2a4..0b8ea1150 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -1111,8 +1111,8 @@ export class DocumentViewInternal extends DocComponent u.user.email === this.dataDoc.author)?.sharingDoc.userColor,
- Doc.UserDoc().layout_showTitle && [DocumentType.RTF, DocumentType.COL].includes(this.rootDoc.type as any) ? StrCast(Doc.SharingDoc().userColor) : 'rgba(0,0,0,0.4)'
+ SharingManager.Instance.users.find(u => u.user.email === this.dataDoc.author)?.sharingDoc.headingColor,
+ Doc.UserDoc().layout_showTitle && [DocumentType.RTF, DocumentType.COL].includes(this.rootDoc.type as any) ? StrCast(Doc.SharingDoc().headingColor) : 'rgba(0,0,0,0.4)'
);
const layout_sidebarWidthPercent = +StrCast(this.layoutDoc.layout_sidebarWidthPercent).replace('%', '');
const titleView = !layout_showTitle ? null : (
diff --git a/src/client/views/nodes/FontIconBox/ButtonInterface.ts b/src/client/views/nodes/FontIconBox/ButtonInterface.ts
new file mode 100644
index 000000000..0aa2ac8e1
--- /dev/null
+++ b/src/client/views/nodes/FontIconBox/ButtonInterface.ts
@@ -0,0 +1,12 @@
+import { Doc } from "../../../../fields/Doc";
+import { IconProp } from "@fortawesome/fontawesome-svg-core";
+import { ButtonType } from "./FontIconBox";
+
+export interface IButtonProps {
+ type: string | ButtonType;
+ rootDoc: Doc;
+ label: any;
+ icon: IconProp;
+ color: string;
+ backgroundColor: string;
+}
\ No newline at end of file
diff --git a/src/client/views/nodes/FontIconBox/FontIconBadge.scss b/src/client/views/nodes/FontIconBox/FontIconBadge.scss
new file mode 100644
index 000000000..78f506e57
--- /dev/null
+++ b/src/client/views/nodes/FontIconBox/FontIconBadge.scss
@@ -0,0 +1,11 @@
+.fontIconBadge {
+ background: red;
+ width: 15px;
+ height: 15px;
+ top: 8px;
+ display: block;
+ position: absolute;
+ right: 5;
+ border-radius: 50%;
+ text-align: center;
+}
\ No newline at end of file
diff --git a/src/client/views/nodes/FontIconBox/FontIconBadge.tsx b/src/client/views/nodes/FontIconBox/FontIconBadge.tsx
new file mode 100644
index 000000000..b50588ce2
--- /dev/null
+++ b/src/client/views/nodes/FontIconBox/FontIconBadge.tsx
@@ -0,0 +1,37 @@
+import { observer } from 'mobx-react';
+import * as React from 'react';
+import './FontIconBadge.scss';
+
+interface FontIconBadgeProps {
+ value: string | undefined;
+}
+
+@observer
+export class FontIconBadge extends React.Component {
+ _notifsRef = React.createRef();
+
+ // onPointerDown = (e: React.PointerEvent) => {
+ // setupMoveUpEvents(this, e,
+ // (e: PointerEvent) => {
+ // const dragData = new DragManager.DocumentDragData([this.props.collection!]);
+ // DragManager.StartDocumentDrag([this._notifsRef.current!], dragData, e.x, e.y);
+ // return true;
+ // },
+ // returnFalse, emptyFunction, false);
+ // }
+
+ render() {
+ if (this.props.value === undefined) return null;
+ return (
+
+
+ {this.props.value}
+
+
+ );
+ }
+}
diff --git a/src/client/views/nodes/FontIconBox/FontIconBox.scss b/src/client/views/nodes/FontIconBox/FontIconBox.scss
new file mode 100644
index 000000000..9d9fa26b0
--- /dev/null
+++ b/src/client/views/nodes/FontIconBox/FontIconBox.scss
@@ -0,0 +1,438 @@
+@import '../../global/globalCssVariables';
+
+.menuButton {
+ height: 100%;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ font-size: 80%;
+ border-radius: $standard-border-radius;
+ transition: 0.15s;
+
+ .menuButton-wrap {
+ grid-column: 1;
+ justify-content: center;
+ align-items: center;
+ text-align: center;
+ }
+
+ .fontIconBox-label {
+ color: $white;
+ bottom: -1;
+ position: absolute;
+ text-align: center;
+ font-size: 7px;
+ letter-spacing: normal;
+ background-color: inherit;
+ border-radius: 8px;
+ padding: 0;
+ width: 100%;
+ font-family: 'system-ui';
+ text-transform: uppercase;
+ font-weight: bold;
+ transition: 0.15s;
+ }
+
+ .fontIconBox-icon {
+ width: 80%;
+ height: 80%;
+ }
+
+ &.clickBtn,
+ &.clickBtnLabel {
+ cursor: pointer;
+ flex-direction: column;
+
+ svg {
+ width: 50% !important;
+ height: 50%;
+ }
+ }
+
+ &.clickBtnLabel {
+ svg {
+ margin-top: -4px;
+ }
+ }
+
+ &.textBtn {
+ display: grid;
+ /* grid-row: auto; */
+ grid-auto-flow: column;
+ cursor: pointer;
+ width: 100%;
+ justify-content: center;
+ align-items: center;
+ justify-items: center;
+ }
+
+ &.tglBtn,
+ &.tglBtnLabel {
+ cursor: pointer;
+ flex-direction: column;
+
+ &.switch {
+ //TOGGLE
+
+ .switch {
+ position: relative;
+ display: inline-block;
+ width: 100%;
+ height: 25px;
+ margin: 0;
+ }
+
+ .switch input {
+ opacity: 0;
+ width: 0;
+ height: 0;
+ }
+
+ .slider {
+ position: absolute;
+ cursor: pointer;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ background-color: lightgrey;
+ -webkit-transition: 0.4s;
+ transition: 0.4s;
+ }
+
+ .slider:before {
+ position: absolute;
+ content: '';
+ height: 21px;
+ width: 21px;
+ left: 2px;
+ bottom: 2px;
+ background-color: $white;
+ -webkit-transition: 0.4s;
+ transition: 0.4s;
+ }
+
+ input:checked + .slider {
+ background-color: $medium-blue;
+ }
+
+ input:focus + .slider {
+ box-shadow: 0 0 1px $medium-blue;
+ }
+
+ input:checked + .slider:before {
+ -webkit-transform: translateX(26px);
+ -ms-transform: translateX(26px);
+ transform: translateX(26px);
+ }
+
+ /* Rounded sliders */
+ .slider.round {
+ border-radius: $standard-border-radius;
+ }
+
+ .slider.round:before {
+ border-radius: $standard-border-radius;
+ }
+ }
+
+ svg {
+ width: 50% !important;
+ height: 50%;
+ }
+
+ &:hover {
+ background-color: rgba(0, 0, 0, 0.3);
+ }
+ }
+
+ &.tglBtnLabel {
+ svg {
+ margin-top: -4px;
+ }
+ }
+
+ &.toolBtn,
+ &.toolBtnLabel {
+ cursor: pointer;
+ width: 100%;
+ border-radius: 100%;
+ flex-direction: column;
+ // margin-top: -4px;
+
+ svg {
+ width: 60% !important;
+ height: 60%;
+ }
+ }
+
+ &.toolBtnLabel {
+ svg {
+ margin-top: -4px;
+ }
+ }
+
+ &.menuBtn {
+ cursor: pointer !important;
+ border-radius: 0px;
+ flex-direction: column;
+
+ svg {
+ width: 45% !important;
+ height: 45%;
+ }
+
+ &:hover {
+ filter: brightness(0.85);
+ }
+ }
+
+ &.colorBtn,
+ &.colorBtnLabel {
+ color: black;
+ cursor: pointer;
+ flex-direction: column;
+ background: transparent;
+
+ .colorButton-color {
+ margin-top: 3px;
+ width: 80%;
+ height: 3px;
+ }
+
+ .menuButton-dropdownBox {
+ position: absolute;
+ width: fit-content;
+ height: fit-content;
+ color: black;
+ top: 100%;
+ left: 0;
+ z-index: 21;
+ background-color: #e3e3e3;
+ box-shadow: 0px 3px 4px rgba(0, 0, 0, 0.3);
+ border-radius: 3px;
+ }
+ }
+
+ &.colorBtnLabel {
+ svg {
+ margin-top: -4px;
+ }
+ }
+
+ &.drpdownList {
+ width: 100%;
+ display: grid;
+ grid-auto-columns: 80px 20px;
+ justify-items: center;
+ font-family: 'Roboto';
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ font-size: 13;
+ font-weight: 600;
+ overflow: hidden;
+ cursor: pointer;
+ background: transparent;
+ align-content: center;
+ align-items: center;
+
+ .menuButton-dropdownList {
+ position: absolute;
+ width: 150px;
+ height: fit-content;
+ top: 100%;
+ z-index: 21;
+ background-color: $white;
+ box-shadow: 0px 3px 4px rgba(0, 0, 0, 0.3);
+ padding: 1px;
+
+ .list-item {
+ color: $black;
+ width: 100%;
+ height: 25px;
+ font-weight: 400;
+ display: flex;
+ justify-content: left;
+ align-items: center;
+ padding-left: 5px;
+ }
+
+ .list-item:hover {
+ background-color: lightgrey;
+ }
+ }
+ }
+
+ &.numBtn {
+ cursor: pointer;
+ background: transparent;
+
+ &.slider {
+ color: $white;
+ cursor: pointer;
+ flex-direction: column;
+ background: transparent;
+
+ .menu-slider {
+ width: 100px;
+ }
+
+ .menuButton-dropdownBox {
+ position: absolute;
+ width: fit-content;
+ height: fit-content;
+ top: 100%;
+ z-index: 21;
+ background-color: #e3e3e3;
+ box-shadow: 0px 3px 4px rgba(0, 0, 0, 0.3);
+ border-radius: $standard-border-radius;
+
+ .menu-slider {
+ height: 10px;
+ }
+ input[type='range']::-webkit-slider-runnable-track {
+ background: gray;
+ height: 3px;
+ }
+
+ input[type='range']::-webkit-slider-thumb {
+ box-shadow: 1px 1px 1px #000000;
+ border: 1px solid #000000;
+ height: 10px;
+ width: 10px;
+ border-radius: 5px;
+ background: #ffffff;
+ cursor: pointer;
+ -webkit-appearance: none;
+ margin-top: -4px;
+ }
+ }
+ }
+
+ .button {
+ width: 25%;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+
+ &.number {
+ width: 50%;
+
+ .button-input {
+ background: none;
+ border: none;
+ text-align: right;
+ width: 100%;
+ color: $white;
+ height: 100%;
+ text-align: center;
+ }
+
+ .button-input:focus {
+ outline: none;
+ }
+ }
+ }
+
+ &.list {
+ width: 100%;
+ justify-content: space-around;
+ border: $standard-border;
+
+ .menuButton-dropdownList {
+ position: absolute;
+ width: fit-content;
+ height: fit-content;
+ min-width: 50%;
+ max-height: 50vh;
+ overflow-y: scroll;
+ top: 100%;
+ z-index: 21;
+ background-color: $white;
+ box-shadow: 0px 3px 4px rgba(0, 0, 0, 0.3);
+ padding: 1px;
+
+ .list-item {
+ color: $black;
+ width: 100%;
+ height: 25px;
+ font-weight: 400;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ }
+
+ .list-item:hover {
+ background-color: lightgrey;
+ }
+ }
+ }
+ }
+
+ &.editableText {
+ cursor: text;
+ display: flex;
+ flex-direction: row;
+ gap: 5px;
+ padding-left: 10px;
+ justify-content: flex-start;
+ color: black;
+ background-color: $light-gray;
+ padding: 5px;
+ padding-left: 10px;
+ width: 100%;
+ height: 100%;
+ }
+
+ &.drpDownBtn {
+ cursor: pointer;
+ background: transparent;
+ border: solid 0.5px grey;
+
+ &.true {
+ background: rgba(0, 0, 0, 0.3);
+ }
+
+ .menuButton-dropdownBox {
+ position: absolute;
+ width: 150px;
+ height: 250px;
+ top: 100%;
+ background-color: #e3e3e3;
+ box-shadow: 0px 3px 4px rgba(0, 0, 0, 0.3);
+ border-radius: $standard-border-radius;
+ }
+ }
+
+ .menuButton-dropdown {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ font-size: 15px;
+ grid-column: 2;
+ border-radius: 0px 7px 7px 0px;
+ width: 13px;
+ height: 100%;
+ right: 0;
+ }
+
+ .menuButton-dropdown-header {
+ width: 100%;
+ font-weight: 300;
+ padding: 5px;
+ overflow: hidden;
+ font-size: 12px;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ }
+
+ .dropbox-background {
+ width: 200vw;
+ height: 200vh;
+ top: -100vh;
+ z-index: 20;
+ left: -100vw;
+ background: transparent;
+ position: fixed;
+ }
+}
diff --git a/src/client/views/nodes/FontIconBox/FontIconBox.tsx b/src/client/views/nodes/FontIconBox/FontIconBox.tsx
new file mode 100644
index 000000000..2958fa737
--- /dev/null
+++ b/src/client/views/nodes/FontIconBox/FontIconBox.tsx
@@ -0,0 +1,412 @@
+import { IconProp } from '@fortawesome/fontawesome-svg-core';
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import { Button, ColorPicker, Dropdown, DropdownType, EditableText, IconButton, IListItemProps, NumberDropdown, NumberDropdownType, Popup, Size, Toggle, ToggleType, Type } from 'browndash-components';
+import { action, computed, observable } from 'mobx';
+import { observer } from 'mobx-react';
+import * as React from 'react';
+import { Doc, DocListCast, StrListCast } from '../../../../fields/Doc';
+import { ScriptField } from '../../../../fields/ScriptField';
+import { BoolCast, Cast, NumCast, ScriptCast, StrCast } from '../../../../fields/Types';
+import { CollectionViewType, DocumentType } from '../../../documents/DocumentTypes';
+import { SelectionManager } from '../../../util/SelectionManager';
+import { undoable, UndoManager } from '../../../util/UndoManager';
+import { ContextMenu } from '../../ContextMenu';
+import { DocComponent } from '../../DocComponent';
+import { EditableView } from '../../EditableView';
+import { Colors } from '../../global/globalEnums';
+import { StyleProp } from '../../StyleProvider';
+import { FieldView, FieldViewProps } from '../FieldView';
+import { OpenWhere } from '../DocumentView';
+import { RichTextMenu } from '../formattedText/RichTextMenu';
+import './FontIconBox.scss';
+import { SelectedDocView } from '../../selectedDoc';
+
+export enum ButtonType {
+ TextButton = 'textBtn',
+ MenuButton = 'menuBtn',
+ DropdownList = 'dropdownList',
+ DropdownButton = 'dropdownBtn',
+ ClickButton = 'clickBtn',
+ ToggleButton = 'toggleBtn',
+ ColorButton = 'colorBtn',
+ ToolButton = 'toolBtn',
+ MultiToggleButton = 'multiToggleBtn',
+ NumberSliderButton = 'numSliderBtn',
+ NumberDropdownButton = 'numDropdownBtn',
+ NumberInlineButton = 'numInlineBtn',
+ EditableText = 'editableText',
+}
+
+export interface ButtonProps extends FieldViewProps {
+ type?: ButtonType;
+}
+@observer
+export class FontIconBox extends DocComponent() {
+ public static LayoutString(fieldKey: string) {
+ return FieldView.LayoutString(FontIconBox, fieldKey);
+ }
+ @observable noTooltip = false;
+ showTemplate = (): void => {
+ const dragFactory = Cast(this.layoutDoc.dragFactory, Doc, null);
+ dragFactory && this.props.addDocTab(dragFactory, OpenWhere.addRight);
+ };
+ dragAsTemplate = (): void => {
+ this.layoutDoc.onDragStart = ScriptField.MakeFunction('getCopy(this.dragFactory, true)');
+ };
+ useAsPrototype = (): void => {
+ this.layoutDoc.onDragStart = ScriptField.MakeFunction('makeDelegate(this.dragFactory, true)');
+ };
+
+ specificContextMenu = (): void => {
+ if (!Doc.noviceMode) {
+ const cm = ContextMenu.Instance;
+ cm.addItem({ description: 'Show Template', event: this.showTemplate, icon: 'tag' });
+ cm.addItem({ description: 'Use as Render Template', event: this.dragAsTemplate, icon: 'tag' });
+ cm.addItem({ description: 'Use as Prototype', event: this.useAsPrototype, icon: 'tag' });
+ }
+ };
+
+ static GetShowLabels() {
+ return BoolCast(Doc.UserDoc()._showLabel);
+ }
+ static SetShowLabels(show: boolean) {
+ Doc.UserDoc()._showLabel = show;
+ }
+ static GetRecognizeGestures() {
+ return BoolCast(Doc.UserDoc()._recognizeGestures);
+ }
+ static SetRecognizeGestures(show: boolean) {
+ Doc.UserDoc()._recognizeGestures = show;
+ }
+
+ // Determining UI Specs
+ @computed get label() {
+ return StrCast(this.rootDoc.icon_label, StrCast(this.rootDoc.title));
+ }
+ Icon = (color: string, iconFalse?: boolean) => {
+ let icon;
+ if (iconFalse ) {
+ icon = StrCast(this.dataDoc[this.fieldKey ?? 'iconFalse'] ?? this.dataDoc.icon, 'user') as any;
+ if (icon) return
+ else return null
+ }
+ icon = StrCast(this.dataDoc[this.fieldKey ?? 'icon'] ?? this.dataDoc.icon, 'user') as any;
+ const trailsIcon = () => ;
+ return !icon ? null : icon === 'pres-trail' ? trailsIcon() : ;
+ };
+ @computed get dropdown() {
+ return BoolCast(this.rootDoc.dropDownOpen);
+ }
+ @computed get buttonList() {
+ return StrListCast(this.rootDoc.btnList);
+ }
+ @computed get type() {
+ return StrCast(this.rootDoc.btnType);
+ }
+
+ /**
+ * Types of buttons in dash:
+ * - Main menu button (LHS)
+ * - Tool button
+ * - Expandable button (CollectionLinearView)
+ * - Button inside of CollectionLinearView vs. outside of CollectionLinearView
+ * - Action button
+ * - Dropdown button
+ * - Color button
+ * - Dropdown list
+ * - Number button
+ **/
+
+ _batch: UndoManager.Batch | undefined = undefined;
+ /**
+ * Number button
+ */
+ @computed get numberDropdown() {
+ let type: NumberDropdownType;
+ switch(this.type) {
+ case ButtonType.NumberDropdownButton:
+ type = 'dropdown'
+ break;
+ case ButtonType.NumberInlineButton:
+ type = 'input'
+ break;
+ case ButtonType.NumberSliderButton:
+ default:
+ type = 'slider'
+ break;
+ }
+ const numScript = (value?: number) => ScriptCast(this.rootDoc.script).script.run({ self: this.rootDoc, value, _readOnly_: value === undefined });
+ const color = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Color);
+ // Script for checking the outcome of the toggle
+ const checkResult = Number(Number(numScript().result ?? 0).toPrecision(NumCast(this.dataDoc.numPrecision, 3)));
+ const label = !FontIconBox.GetShowLabels() ? null : {this.label}
;
+
+ return numScript(value), `${this.rootDoc.title} button set from list`)}
+ fillWidth
+ />
+ }
+
+ /**
+ * Dropdown button
+ */
+ @computed get dropdownButton() {
+ const active: string = StrCast(this.rootDoc.dropDownOpen);
+ const color = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Color);
+ const backgroundColor = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor);
+ return (
+ {
+ this.rootDoc.dropDownOpen = !this.rootDoc.dropDownOpen;
+ this.noTooltip = this.rootDoc.dropDownOpen;
+ Doc.UnBrushAllDocs();
+ })}>
+ {this.Icon(color)}
+ {!this.label || !FontIconBox.GetShowLabels() ? null : (
+
+ {' '}
+ {this.label}{' '}
+
+ )}
+
+
+
+ {this.rootDoc.dropDownOpen ?
{/* DROPDOWN BOX CONTENTS */}
: null}
+
+ );
+ }
+
+ /**
+ * Dropdown list
+ */
+ @computed get dropdownListButton() {
+ const active: string = StrCast(this.rootDoc.dropDownOpen);
+ const color = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Color);
+ const backgroundColor = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor);
+
+ const script = ScriptCast(this.rootDoc.script);
+
+ let noviceList: string[] = [];
+ let text: string | undefined;
+ let dropdown = true;
+ let getStyle: (val: string) => any = () => {};
+ let icon: IconProp = 'caret-down';
+ let isViewDropdown: boolean = script?.script.originalScript.startsWith('setView')
+ try {
+ if (isViewDropdown) {
+ const selectedDocs: Doc[] = SelectionManager.Docs();
+ const selected = SelectionManager.Docs().lastElement();
+ console.log('selected')
+ if (selected) {
+ if (StrCast(selected.type) === DocumentType.COL) {
+ text = StrCast(selected._type_collection);
+ } else {
+ console.log("doc selected", selected.title);
+ dropdown = false;
+ if (selectedDocs.length > 1) {
+ text = selectedDocs.length + " documents selected"
+ } else {
+ text = selected.type === DocumentType.RTF ? 'Text' : StrCast(selected.type);
+ icon = Doc.toIcon(selected);
+ }
+ return }
+ text={text}
+ type={Type.TERT}
+ color={color}
+ popup={}
+ fillWidth
+ />
+ }
+ } else {
+ dropdown = false;
+ return
+ }
+ noviceList = [CollectionViewType.Freeform, CollectionViewType.Schema, CollectionViewType.Stacking, CollectionViewType.NoteTaking];
+ } else {
+ text = StrCast((RichTextMenu.Instance?.TextView?.EditorView ? RichTextMenu.Instance : Doc.UserDoc()).fontFamily);
+ getStyle = (val: string) => { return { fontFamily: val } }
+ }
+ } catch (e) {
+ console.log(e);
+ }
+
+ console.log("current item: ", text);
+
+ // Get items to place into the list
+ const list: IListItemProps[] = this.buttonList
+ .filter(value => !Doc.noviceMode || !noviceList.length || noviceList.includes(value))
+ .map(value => (
+ {
+ text: value.charAt(0).toUpperCase() + value.slice(1),
+ val: value,
+ style: getStyle(value),
+ onClick: undoable(() => script.script.run({ self: this.rootDoc, value }), value)
+ // shortcut: '#',
+ }
+ ));
+
+
+ return (
+ script.script.run({ self: this.rootDoc, val }), `dropdown select ${this.label}`)}
+ color={color}
+ type={isViewDropdown ? Type.TERT : Type.PRIM}
+ dropdownType={DropdownType.SELECT}
+ items={list}
+ tooltip={this.label}
+ fillWidth
+ />
+ )
+ }
+
+
+ @computed get colorScript() {
+ return ScriptCast(this.rootDoc.script);
+ }
+
+ /**
+ * Color button
+ */
+ @computed get colorButton() {
+ const color = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Color);
+ const backgroundColor = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor);
+ const curColor = this.colorScript?.script.run({ self: this.rootDoc, value: undefined, _readOnly_: true }).result ?? 'transparent';
+ const tooltip: string = StrCast(this.rootDoc.toolTip);
+
+ return (
+ {
+ const s = this.colorScript;
+ s && undoable(() => s.script.run({ self: this.rootDoc, value: value, _readOnly_: false }).result, `Set ${tooltip} to ${value}`)();
+ }}
+ selectedColor={curColor}
+ type={Type.PRIM}
+ color={color}
+ icon={this.Icon(color)!}
+ tooltip={tooltip}
+ label={this.label}
+ />
+ )
+ }
+
+ @computed get toggleButton() {
+ // Determine the type of toggle button
+ const buttonText: string = StrCast(this.rootDoc.buttonText);
+ const tooltip: string = StrCast(this.rootDoc.toolTip);
+
+ const script = ScriptCast(this.rootDoc.onClick);
+ const toggleStatus = script ? script.script.run({ self: this.rootDoc, value: undefined, _readOnly_: true }).result : false;
+ // Colors
+ const color = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Color);
+ const backgroundColor = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor);
+
+ console.log(tooltip, toggleStatus);
+ return (
+
+ )
+ }
+
+ /**
+ * Default
+ */
+ @computed get defaultButton() {
+ const color = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Color);
+ const backgroundColor = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor);
+ const tooltip: string = StrCast(this.rootDoc.toolTip);
+
+ return (
+
+ )
+ }
+
+ @computed get editableText() {
+ // Script for running the toggle
+ const script = ScriptCast(this.rootDoc.script);
+ // Function to run the script
+ const checkResult = script?.script.run({ value: '', _readOnly_: true }).result;
+
+ const setValue = (value: string, shiftDown?: boolean): boolean => script?.script.run({ value, _readOnly_: false }).result;
+
+ return {}}
+ />
+
+ return (
+
+
+
+ script?.script.run({ value: '', _readOnly_: true }).result} SetValue={setValue} oneLine={true} contents={checkResult} />
+
+
+ );
+ }
+
+ render() {
+ // determine dash button metadata
+ const color = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Color);
+ const backgroundColor = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor);
+ const tooltip: string = StrCast(this.rootDoc.toolTip);
+
+ // TODO:glr Add label of button type
+ let button: JSX.Element = this.defaultButton;
+ // prettier-ignore
+ switch (this.type) {
+ case ButtonType.EditableText:
+ button = this.editableText;
+ break;
+ case ButtonType.DropdownList:
+ button = this.dropdownListButton;
+ break;
+ case ButtonType.ColorButton:
+ button = this.colorButton;
+ break;
+ case ButtonType.NumberDropdownButton:
+ case ButtonType.NumberInlineButton:
+ case ButtonType.NumberSliderButton:
+ button = this.numberDropdown;
+ break;
+ case ButtonType.DropdownButton:
+ button = this.dropdownButton;
+ break;
+ case ButtonType.ToggleButton: button = this.toggleButton; break;
+ case ButtonType.TextButton:
+ // Script for checking the outcome of the toggle
+ const script = ScriptCast(this.rootDoc.script);
+ const checkResult = script?.script.run({ _readOnly_: true }).result;
+ button = (
+
+ );
+ break;
+ case ButtonType.ClickButton:
+ case ButtonType.ToolButton:
+ button = (
+
+ );
+ break;
+ case ButtonType.MenuButton: button = (
+
+ );
+ break;
+ }
+
+ return button;
+ }
+}
diff --git a/src/client/views/nodes/button/FontIconBox.scss b/src/client/views/nodes/button/FontIconBox.scss
deleted file mode 100644
index 9d9fa26b0..000000000
--- a/src/client/views/nodes/button/FontIconBox.scss
+++ /dev/null
@@ -1,438 +0,0 @@
-@import '../../global/globalCssVariables';
-
-.menuButton {
- height: 100%;
- display: flex;
- justify-content: center;
- align-items: center;
- font-size: 80%;
- border-radius: $standard-border-radius;
- transition: 0.15s;
-
- .menuButton-wrap {
- grid-column: 1;
- justify-content: center;
- align-items: center;
- text-align: center;
- }
-
- .fontIconBox-label {
- color: $white;
- bottom: -1;
- position: absolute;
- text-align: center;
- font-size: 7px;
- letter-spacing: normal;
- background-color: inherit;
- border-radius: 8px;
- padding: 0;
- width: 100%;
- font-family: 'system-ui';
- text-transform: uppercase;
- font-weight: bold;
- transition: 0.15s;
- }
-
- .fontIconBox-icon {
- width: 80%;
- height: 80%;
- }
-
- &.clickBtn,
- &.clickBtnLabel {
- cursor: pointer;
- flex-direction: column;
-
- svg {
- width: 50% !important;
- height: 50%;
- }
- }
-
- &.clickBtnLabel {
- svg {
- margin-top: -4px;
- }
- }
-
- &.textBtn {
- display: grid;
- /* grid-row: auto; */
- grid-auto-flow: column;
- cursor: pointer;
- width: 100%;
- justify-content: center;
- align-items: center;
- justify-items: center;
- }
-
- &.tglBtn,
- &.tglBtnLabel {
- cursor: pointer;
- flex-direction: column;
-
- &.switch {
- //TOGGLE
-
- .switch {
- position: relative;
- display: inline-block;
- width: 100%;
- height: 25px;
- margin: 0;
- }
-
- .switch input {
- opacity: 0;
- width: 0;
- height: 0;
- }
-
- .slider {
- position: absolute;
- cursor: pointer;
- top: 0;
- left: 0;
- right: 0;
- bottom: 0;
- background-color: lightgrey;
- -webkit-transition: 0.4s;
- transition: 0.4s;
- }
-
- .slider:before {
- position: absolute;
- content: '';
- height: 21px;
- width: 21px;
- left: 2px;
- bottom: 2px;
- background-color: $white;
- -webkit-transition: 0.4s;
- transition: 0.4s;
- }
-
- input:checked + .slider {
- background-color: $medium-blue;
- }
-
- input:focus + .slider {
- box-shadow: 0 0 1px $medium-blue;
- }
-
- input:checked + .slider:before {
- -webkit-transform: translateX(26px);
- -ms-transform: translateX(26px);
- transform: translateX(26px);
- }
-
- /* Rounded sliders */
- .slider.round {
- border-radius: $standard-border-radius;
- }
-
- .slider.round:before {
- border-radius: $standard-border-radius;
- }
- }
-
- svg {
- width: 50% !important;
- height: 50%;
- }
-
- &:hover {
- background-color: rgba(0, 0, 0, 0.3);
- }
- }
-
- &.tglBtnLabel {
- svg {
- margin-top: -4px;
- }
- }
-
- &.toolBtn,
- &.toolBtnLabel {
- cursor: pointer;
- width: 100%;
- border-radius: 100%;
- flex-direction: column;
- // margin-top: -4px;
-
- svg {
- width: 60% !important;
- height: 60%;
- }
- }
-
- &.toolBtnLabel {
- svg {
- margin-top: -4px;
- }
- }
-
- &.menuBtn {
- cursor: pointer !important;
- border-radius: 0px;
- flex-direction: column;
-
- svg {
- width: 45% !important;
- height: 45%;
- }
-
- &:hover {
- filter: brightness(0.85);
- }
- }
-
- &.colorBtn,
- &.colorBtnLabel {
- color: black;
- cursor: pointer;
- flex-direction: column;
- background: transparent;
-
- .colorButton-color {
- margin-top: 3px;
- width: 80%;
- height: 3px;
- }
-
- .menuButton-dropdownBox {
- position: absolute;
- width: fit-content;
- height: fit-content;
- color: black;
- top: 100%;
- left: 0;
- z-index: 21;
- background-color: #e3e3e3;
- box-shadow: 0px 3px 4px rgba(0, 0, 0, 0.3);
- border-radius: 3px;
- }
- }
-
- &.colorBtnLabel {
- svg {
- margin-top: -4px;
- }
- }
-
- &.drpdownList {
- width: 100%;
- display: grid;
- grid-auto-columns: 80px 20px;
- justify-items: center;
- font-family: 'Roboto';
- white-space: nowrap;
- text-overflow: ellipsis;
- font-size: 13;
- font-weight: 600;
- overflow: hidden;
- cursor: pointer;
- background: transparent;
- align-content: center;
- align-items: center;
-
- .menuButton-dropdownList {
- position: absolute;
- width: 150px;
- height: fit-content;
- top: 100%;
- z-index: 21;
- background-color: $white;
- box-shadow: 0px 3px 4px rgba(0, 0, 0, 0.3);
- padding: 1px;
-
- .list-item {
- color: $black;
- width: 100%;
- height: 25px;
- font-weight: 400;
- display: flex;
- justify-content: left;
- align-items: center;
- padding-left: 5px;
- }
-
- .list-item:hover {
- background-color: lightgrey;
- }
- }
- }
-
- &.numBtn {
- cursor: pointer;
- background: transparent;
-
- &.slider {
- color: $white;
- cursor: pointer;
- flex-direction: column;
- background: transparent;
-
- .menu-slider {
- width: 100px;
- }
-
- .menuButton-dropdownBox {
- position: absolute;
- width: fit-content;
- height: fit-content;
- top: 100%;
- z-index: 21;
- background-color: #e3e3e3;
- box-shadow: 0px 3px 4px rgba(0, 0, 0, 0.3);
- border-radius: $standard-border-radius;
-
- .menu-slider {
- height: 10px;
- }
- input[type='range']::-webkit-slider-runnable-track {
- background: gray;
- height: 3px;
- }
-
- input[type='range']::-webkit-slider-thumb {
- box-shadow: 1px 1px 1px #000000;
- border: 1px solid #000000;
- height: 10px;
- width: 10px;
- border-radius: 5px;
- background: #ffffff;
- cursor: pointer;
- -webkit-appearance: none;
- margin-top: -4px;
- }
- }
- }
-
- .button {
- width: 25%;
- display: flex;
- align-items: center;
- justify-content: center;
-
- &.number {
- width: 50%;
-
- .button-input {
- background: none;
- border: none;
- text-align: right;
- width: 100%;
- color: $white;
- height: 100%;
- text-align: center;
- }
-
- .button-input:focus {
- outline: none;
- }
- }
- }
-
- &.list {
- width: 100%;
- justify-content: space-around;
- border: $standard-border;
-
- .menuButton-dropdownList {
- position: absolute;
- width: fit-content;
- height: fit-content;
- min-width: 50%;
- max-height: 50vh;
- overflow-y: scroll;
- top: 100%;
- z-index: 21;
- background-color: $white;
- box-shadow: 0px 3px 4px rgba(0, 0, 0, 0.3);
- padding: 1px;
-
- .list-item {
- color: $black;
- width: 100%;
- height: 25px;
- font-weight: 400;
- display: flex;
- justify-content: center;
- align-items: center;
- }
-
- .list-item:hover {
- background-color: lightgrey;
- }
- }
- }
- }
-
- &.editableText {
- cursor: text;
- display: flex;
- flex-direction: row;
- gap: 5px;
- padding-left: 10px;
- justify-content: flex-start;
- color: black;
- background-color: $light-gray;
- padding: 5px;
- padding-left: 10px;
- width: 100%;
- height: 100%;
- }
-
- &.drpDownBtn {
- cursor: pointer;
- background: transparent;
- border: solid 0.5px grey;
-
- &.true {
- background: rgba(0, 0, 0, 0.3);
- }
-
- .menuButton-dropdownBox {
- position: absolute;
- width: 150px;
- height: 250px;
- top: 100%;
- background-color: #e3e3e3;
- box-shadow: 0px 3px 4px rgba(0, 0, 0, 0.3);
- border-radius: $standard-border-radius;
- }
- }
-
- .menuButton-dropdown {
- display: flex;
- justify-content: center;
- align-items: center;
- font-size: 15px;
- grid-column: 2;
- border-radius: 0px 7px 7px 0px;
- width: 13px;
- height: 100%;
- right: 0;
- }
-
- .menuButton-dropdown-header {
- width: 100%;
- font-weight: 300;
- padding: 5px;
- overflow: hidden;
- font-size: 12px;
- white-space: nowrap;
- text-overflow: ellipsis;
- }
-
- .dropbox-background {
- width: 200vw;
- height: 200vh;
- top: -100vh;
- z-index: 20;
- left: -100vw;
- background: transparent;
- position: fixed;
- }
-}
diff --git a/src/client/views/nodes/button/FontIconBox.tsx b/src/client/views/nodes/button/FontIconBox.tsx
deleted file mode 100644
index e31407f4b..000000000
--- a/src/client/views/nodes/button/FontIconBox.tsx
+++ /dev/null
@@ -1,385 +0,0 @@
-import { IconProp } from '@fortawesome/fontawesome-svg-core';
-import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { Button, ColorPicker, Dropdown, DropdownType, EditableText, IconButton, IListItemProps, NumberDropdown, NumberDropdownType, Size, Toggle, ToggleType, Type } from 'browndash-components';
-import { action, computed, observable } from 'mobx';
-import { observer } from 'mobx-react';
-import * as React from 'react';
-import { Doc, StrListCast } from '../../../../fields/Doc';
-import { ScriptField } from '../../../../fields/ScriptField';
-import { BoolCast, Cast, NumCast, ScriptCast, StrCast } from '../../../../fields/Types';
-import { CollectionViewType, DocumentType } from '../../../documents/DocumentTypes';
-import { SelectionManager } from '../../../util/SelectionManager';
-import { undoable, UndoManager } from '../../../util/UndoManager';
-import { ContextMenu } from '../../ContextMenu';
-import { DocComponent } from '../../DocComponent';
-import { EditableView } from '../../EditableView';
-import { Colors } from '../../global/globalEnums';
-import { StyleProp } from '../../StyleProvider';
-import { FieldView, FieldViewProps } from '.././FieldView';
-import { OpenWhere } from '../DocumentView';
-import { RichTextMenu } from '../formattedText/RichTextMenu';
-import './FontIconBox.scss';
-
-export enum ButtonType {
- TextButton = 'textBtn',
- MenuButton = 'menuBtn',
- DropdownList = 'drpdownList',
- DropdownButton = 'drpdownBtn',
- ClickButton = 'clickBtn',
- DoubleButton = 'dblBtn',
- ToggleButton = 'tglBtn',
- ColorButton = 'colorBtn',
- ToolButton = 'toolBtn',
- NumberSliderButton = 'numSliderBtn',
- NumberDropdownButton = 'numDropdownBtn',
- NumberInlineButton = 'numInlineBtn',
- EditableText = 'editableText',
-}
-
-export interface ButtonProps extends FieldViewProps {
- type?: ButtonType;
-}
-@observer
-export class FontIconBox extends DocComponent() {
- public static LayoutString(fieldKey: string) {
- return FieldView.LayoutString(FontIconBox, fieldKey);
- }
- @observable noTooltip = false;
- showTemplate = (): void => {
- const dragFactory = Cast(this.layoutDoc.dragFactory, Doc, null);
- dragFactory && this.props.addDocTab(dragFactory, OpenWhere.addRight);
- };
- dragAsTemplate = (): void => {
- this.layoutDoc.onDragStart = ScriptField.MakeFunction('getCopy(this.dragFactory, true)');
- };
- useAsPrototype = (): void => {
- this.layoutDoc.onDragStart = ScriptField.MakeFunction('makeDelegate(this.dragFactory, true)');
- };
-
- specificContextMenu = (): void => {
- if (!Doc.noviceMode) {
- const cm = ContextMenu.Instance;
- cm.addItem({ description: 'Show Template', event: this.showTemplate, icon: 'tag' });
- cm.addItem({ description: 'Use as Render Template', event: this.dragAsTemplate, icon: 'tag' });
- cm.addItem({ description: 'Use as Prototype', event: this.useAsPrototype, icon: 'tag' });
- }
- };
-
- static GetShowLabels() {
- return BoolCast(Doc.UserDoc()._showLabel);
- }
- static SetShowLabels(show: boolean) {
- Doc.UserDoc()._showLabel = show;
- }
- static GetRecognizeGestures() {
- return BoolCast(Doc.UserDoc()._recognizeGestures);
- }
- static SetRecognizeGestures(show: boolean) {
- Doc.UserDoc()._recognizeGestures = show;
- }
-
- // Determining UI Specs
- @computed get label() {
- return StrCast(this.rootDoc.icon_label, StrCast(this.rootDoc.title));
- }
- Icon = (color: string, iconFalse?: boolean) => {
- let icon;
- if (iconFalse ) {
- icon = StrCast(this.dataDoc[this.fieldKey ?? 'iconFalse'] ?? this.dataDoc.icon, 'user') as any;
- if (icon) return
- else return null
- }
- icon = StrCast(this.dataDoc[this.fieldKey ?? 'icon'] ?? this.dataDoc.icon, 'user') as any;
- const trailsIcon = () => ;
- return !icon ? null : icon === 'pres-trail' ? trailsIcon() : ;
- };
- @computed get dropdown() {
- return BoolCast(this.rootDoc.dropDownOpen);
- }
- @computed get buttonList() {
- return StrListCast(this.rootDoc.btnList);
- }
- @computed get type() {
- return StrCast(this.rootDoc.btnType);
- }
-
- /**
- * Types of buttons in dash:
- * - Main menu button (LHS)
- * - Tool button
- * - Expandable button (CollectionLinearView)
- * - Button inside of CollectionLinearView vs. outside of CollectionLinearView
- * - Action button
- * - Dropdown button
- * - Color button
- * - Dropdown list
- * - Number button
- **/
-
- _batch: UndoManager.Batch | undefined = undefined;
- /**
- * Number button
- */
- @computed get numberDropdown() {
- let type: NumberDropdownType;
- switch(this.type) {
- case ButtonType.NumberDropdownButton:
- type = 'dropdown'
- break;
- case ButtonType.NumberInlineButton:
- type = 'input'
- break;
- case ButtonType.NumberSliderButton:
- default:
- type = 'slider'
- break;
- }
- const numScript = (value?: number) => ScriptCast(this.rootDoc.script).script.run({ self: this.rootDoc, value, _readOnly_: value === undefined });
- const color = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Color);
- // Script for checking the outcome of the toggle
- const checkResult = Number(Number(numScript().result ?? 0).toPrecision(NumCast(this.dataDoc.numPrecision, 3)));
- const label = !FontIconBox.GetShowLabels() ? null : {this.label}
;
-
- return numScript(value), `${this.rootDoc.title} button set from list`)}
- />
- }
-
- /**
- * Dropdown button
- */
- @computed get dropdownButton() {
- const active: string = StrCast(this.rootDoc.dropDownOpen);
- const color = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Color);
- const backgroundColor = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor);
- return (
- {
- this.rootDoc.dropDownOpen = !this.rootDoc.dropDownOpen;
- this.noTooltip = this.rootDoc.dropDownOpen;
- Doc.UnBrushAllDocs();
- })}>
- {this.Icon(color)}
- {!this.label || !FontIconBox.GetShowLabels() ? null : (
-
- {' '}
- {this.label}{' '}
-
- )}
-
-
-
- {this.rootDoc.dropDownOpen ?
{/* DROPDOWN BOX CONTENTS */}
: null}
-
- );
- }
-
- /**
- * Dropdown list
- */
- @computed get dropdownListButton() {
- const active: string = StrCast(this.rootDoc.dropDownOpen);
- const color = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Color);
- const backgroundColor = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor);
-
- const script = ScriptCast(this.rootDoc.script);
-
- let noviceList: string[] = [];
- let text: string | undefined;
- let dropdown = true;
- let icon: IconProp = 'caret-down';
- try {
- if (script?.script.originalScript.startsWith('setView')) {
- const selected = SelectionManager.Docs().lastElement();
- console.log('selected')
- if (selected) {
- if (StrCast(selected.type) === DocumentType.COL) {
- text = StrCast(selected._type_collection);
- } else {
- console.log("doc selected", selected.title)
- dropdown = false;
- text = selected.type === DocumentType.RTF ? 'Text' : StrCast(selected.type);
- icon = Doc.toIcon(selected);
- return Hi!
- }
- } else {
- dropdown = false;
- icon = 'globe-asia';
- text = 'User Default';
- return Hi!
- }
- noviceList = [CollectionViewType.Freeform, CollectionViewType.Schema, CollectionViewType.Stacking, CollectionViewType.NoteTaking];
- } else text = StrCast((RichTextMenu.Instance?.TextView?.EditorView ? RichTextMenu.Instance : Doc.UserDoc()).fontFamily);
- } catch (e) {
- console.log(e);
- }
-
- console.log("current item: ", text);
-
- // Get items to place into the list
- const list: IListItemProps[] = this.buttonList
- .filter(value => !Doc.noviceMode || !noviceList.length || noviceList.includes(value))
- .map(value => (
- {
- text: value,
- val: value,
- style: { fontFamily: value },
- onClick: undoable(() => script.script.run({ self: this.rootDoc, value }), value)
- // shortcut: '#',
- }
- ));
-
-
- return (
- script.script.run({ self: this.rootDoc, val }), `dropdown select ${this.label}`)}
- color={Colors.WHITE}
- type={Type.PRIM}
- dropdownType={DropdownType.SELECT}
- items={list}
- tooltip={this.label}
- />
- )
- }
-
-
- @computed get colorScript() {
- return ScriptCast(this.rootDoc.script);
- }
-
- /**
- * Color button
- */
- @computed get colorButton() {
- const color = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Color);
- const backgroundColor = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor);
- const curColor = this.colorScript?.script.run({ self: this.rootDoc, value: undefined, _readOnly_: true }).result ?? 'transparent';
- const tooltip: string = StrCast(this.rootDoc.toolTip);
-
- return (
- {
- const s = this.colorScript;
- s && undoable(() => s.script.run({ self: this.rootDoc, value: value, _readOnly_: false }).result, `Set ${tooltip} to ${value}`)();
- }}
- selectedColor={curColor}
- type={Type.PRIM}
- color={color}
- icon={this.Icon(color)!}
- tooltip={tooltip}
- label={this.label}
- />
- )
- }
-
- @computed get toggleButton() {
- // Determine the type of toggle button
- const switchToggle: boolean = BoolCast(this.rootDoc.switchToggle);
- const buttonText: string = StrCast(this.rootDoc.buttonText);
- const tooltip: string = StrCast(this.rootDoc.toolTip);
-
- // Colors
- const color = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Color);
- const backgroundColor = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor);
-
- console.log(buttonText, tooltip);
- return (
-
- )
- }
-
- /**
- * Default
- */
- @computed get defaultButton() {
- const color = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Color);
- const backgroundColor = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor);
- const tooltip: string = StrCast(this.rootDoc.toolTip);
-
- return (
-
- )
- }
-
- @computed get editableText() {
- // Script for running the toggle
- const script = ScriptCast(this.rootDoc.script);
- // Function to run the script
- const checkResult = script?.script.run({ value: '', _readOnly_: true }).result;
-
- const setValue = (value: string, shiftDown?: boolean): boolean => script?.script.run({ value, _readOnly_: false }).result;
-
- return {}} setEditing={(editing: boolean) => {}}
- />
-
- return (
-
-
-
- script?.script.run({ value: '', _readOnly_: true }).result} SetValue={setValue} oneLine={true} contents={checkResult} />
-
-
- );
- }
-
- render() {
- // determine dash button metadata
- const color = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.Color);
- const backgroundColor = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor);
- const tooltip: string = StrCast(this.rootDoc.toolTip);
-
- // TODO:glr Add label of button type
- let button: JSX.Element = this.defaultButton;
- // prettier-ignore
- switch (this.type) {
- case ButtonType.EditableText:
- button = this.editableText;
- break;
- case ButtonType.DropdownList:
- button = this.dropdownListButton;
- break;
- case ButtonType.ColorButton:
- button = this.colorButton;
- break;
- case ButtonType.NumberDropdownButton:
- case ButtonType.NumberInlineButton:
- case ButtonType.NumberSliderButton:
- button = this.numberDropdown;
- break;
- case ButtonType.DropdownButton:
- button = this.dropdownButton;
- break;
- case ButtonType.ToggleButton: button = this.toggleButton; break;
- case ButtonType.TextButton:
- // Script for checking the outcome of the toggle
- const script = ScriptCast(this.rootDoc.script);
- const checkResult = script?.script.run({ _readOnly_: true }).result;
- button = (
-
- );
- break;
- case ButtonType.ClickButton:
- case ButtonType.ToolButton:
- button = (
-
- );
- break;
- case ButtonType.MenuButton: button = (
-
- );
- break;
- }
-
- return button;
- }
-}
diff --git a/src/client/views/pdf/AnchorMenu.tsx b/src/client/views/pdf/AnchorMenu.tsx
index 5480600b0..64ea4f52c 100644
--- a/src/client/views/pdf/AnchorMenu.tsx
+++ b/src/client/views/pdf/AnchorMenu.tsx
@@ -15,6 +15,8 @@ import { GPTPopup, GPTPopupMode } from './GPTPopup/GPTPopup';
import { LightboxView } from '../LightboxView';
import { EditorView } from 'prosemirror-view';
import './AnchorMenu.scss';
+import { ColorPicker, Group, IconButton, Popup, Size, Type } from 'browndash-components';
+import { StrCast } from '../../../fields/Types';
@observer
export class AnchorMenu extends AntimodeMenu {
@@ -42,7 +44,6 @@ export class AnchorMenu extends AntimodeMenu {
];
@observable private highlightColor: string = 'rgba(245, 230, 95, 0.616)';
- @observable private _showLinkPopup: boolean = false;
@observable public Status: 'marquee' | 'annotation' | '' = '';
@@ -131,7 +132,6 @@ export class AnchorMenu extends AntimodeMenu {
() => this._opacity,
opacity => {
if (!opacity) {
- this._showLinkPopup = false;
this.setGPTPopupVis(false);
this.setGPTPopupText('');
}
@@ -141,7 +141,6 @@ export class AnchorMenu extends AntimodeMenu {
this._disposer = reaction(
() => SelectionManager.Views().slice(),
selected => {
- this._showLinkPopup = false;
this.setGPTPopupVis(false);
this.setGPTPopupText('');
AnchorMenu.Instance.fadeOut(true);
@@ -253,49 +252,25 @@ export class AnchorMenu extends AntimodeMenu {
AnchorMenu.Instance.fadeOut(true);
};
- @action
- toggleLinkPopup = (e: React.MouseEvent) => {
- //ignore the potential null type error because this method cannot be called unless the user selects text and clicks the link button
- //change popup visibility field to visible
- this._showLinkPopup = !this._showLinkPopup;
- };
-
@computed get highlighter() {
- const button = (
-
-
-
- );
-
- const dropdownContent = (
-
-
Change highlighter color:
-
- {this._palette.map(color => {
- if (color) {
- return this.highlightColor === color ? (
- this.changeHighlightColor(color, e)}>
- ) : (
- this.changeHighlightColor(color, e)}>
- );
- }
- })}
-
-
- );
- return (
- {'Click to Highlight'} }>
-
-
-
-
- );
+ return
+ }
+ tooltip={'Click to Highlight'}
+ onClick={this.highlightClicked}
+ colorPicker={this.highlightColor}
+ color={StrCast(Doc.UserDoc().userColor)}
+ />
+ this.changeHighlightColor(color)}
+ size={Size.XSMALL}
+ />
+
}
- @action changeHighlightColor = (color: string, e: React.PointerEvent) => {
+ @action changeHighlightColor = (color: string) => {
const col: ColorState = {
hex: color,
hsl: { a: 0, h: 0, s: 0, l: 0, source: '' },
@@ -304,8 +279,6 @@ export class AnchorMenu extends AntimodeMenu
{
oldHue: 0,
source: '',
};
- e.preventDefault();
- e.stopPropagation();
this.highlightColor = Utils.colorString(col);
};
@@ -339,11 +312,12 @@ export class AnchorMenu extends AntimodeMenu {
this.Status === 'marquee' ? (
<>
{this.highlighter}
- Drag to Place Annotation }>
-
-
-
-
+
}
+ color={StrCast(Doc.UserDoc().userColor)}
+ />
{/* GPT Summarize icon only shows up when text is highlighted, not on marquee selection*/}
{AnchorMenu.Instance.StartCropDrag === unimplementedFunction && this.canSummarize() && (
Summarize with AI }>
@@ -364,32 +338,35 @@ export class AnchorMenu extends AntimodeMenu {
mode={this.GPTMode}
/>
{AnchorMenu.Instance.OnAudio === unimplementedFunction ? null : (
- Click to Record Annotation }>
-