diff options
-rw-r--r-- | src/client/util/RichTextMenu.scss | 64 | ||||
-rw-r--r-- | src/client/util/RichTextMenu.tsx | 58 | ||||
-rw-r--r-- | src/client/util/SelectionManager.ts | 3 | ||||
-rw-r--r-- | src/client/util/TooltipTextMenu.tsx | 2 | ||||
-rw-r--r-- | src/client/views/DocumentDecorations.tsx | 8 | ||||
-rw-r--r-- | src/client/views/nodes/FormattedTextBox.tsx | 7 |
6 files changed, 113 insertions, 29 deletions
diff --git a/src/client/util/RichTextMenu.scss b/src/client/util/RichTextMenu.scss index f7414cc7f..85d2765e3 100644 --- a/src/client/util/RichTextMenu.scss +++ b/src/client/util/RichTextMenu.scss @@ -20,9 +20,73 @@ box-shadow: 3px 3px 3px rgba(0, 0, 0, 0.25); min-width: 150px; padding: 5px; + + button { + background-color: #323232; + border: 1px solid black; + border-radius: 1px; + padding: 6px; + margin: 5px 0; + + &:hover { + background-color: black; + } + } } input { color: black; } +} + +.link-menu { + .divider { + background-color: white; + height: 1px; + width: 100%; + } +} + +.color-preview-button { + .color-preview { + width: 100%; + height: 3px; + margin-top: 3px; + } +} + +.color-wrapper { + display: flex; + flex-wrap: wrap; + justify-content: space-between; + + button.color-button { + width: 20px; + height: 20px; + border-radius: 15px !important; + margin: 3px; + border: 2px solid transparent !important; + padding: 3px; + + &.active { + border: 2px solid white !important; + } + } +} + +select { + background-color: #323232; + color: white; + border: 1px solid black; + border-top: none; + border-bottom: none; + + &:focus, + &:hover { + background-color: black; + } + + &::-ms-expand { + color: white; + } }
\ No newline at end of file diff --git a/src/client/util/RichTextMenu.tsx b/src/client/util/RichTextMenu.tsx index 111822307..8c373b818 100644 --- a/src/client/util/RichTextMenu.tsx +++ b/src/client/util/RichTextMenu.tsx @@ -29,6 +29,7 @@ library.add(faBold, faItalic, faUnderline, faStrikethrough, faSuperscript, faSub @observer export default class RichTextMenu extends AntimodeMenu { static Instance: RichTextMenu; + @observable private isVisible: boolean = false; private view?: EditorView; private editorProps: FieldViewProps & FormattedTextBoxProps | undefined; @@ -53,7 +54,6 @@ export default class RichTextMenu extends AntimodeMenu { constructor(props: Readonly<{}>) { super(props); RichTextMenu.Instance = this; - this.Pinned = true; } @action @@ -73,6 +73,7 @@ export default class RichTextMenu extends AntimodeMenu { } this.view = view; const state = view.state; + this.isVisible = true; // DocumentDecorations.Instance.showTextBar(); props && (this.editorProps = props); // Don't do anything if the document/selection didn't change @@ -146,7 +147,6 @@ export default class RichTextMenu extends AntimodeMenu { } destroy() { - console.log("destroy"); } createButton(faIcon: string, title: string, command?: any, onclick?: any) { @@ -213,7 +213,6 @@ export default class RichTextMenu extends AntimodeMenu { } changeFontSize = (mark: Mark, view: EditorView) => { - console.log("change font size!!"); const size = mark.attrs.fontSize; if (this.editorProps) { const ruleProvider = this.editorProps.ruleProvider; @@ -241,9 +240,7 @@ export default class RichTextMenu extends AntimodeMenu { // TODO: remove doesn't work //remove all node type and apply the passed-in one to the selected text changeListType = (nodeType: NodeType | undefined) => { - console.log("change the list type "); if (!this.view) return; - console.log("change the list type has view"); if (nodeType === schema.nodes.bullet_list) { wrapInList(nodeType)(this.view.state, this.view.dispatch); @@ -354,7 +351,6 @@ export default class RichTextMenu extends AntimodeMenu { this.brushIsEmpty = !this.brushIsEmpty; } } - console.log("brush marks are ", this.brushMarks); } @action toggleColorDropdown() { this.showColorDropdown = !this.showColorDropdown; } @@ -397,13 +393,23 @@ export default class RichTextMenu extends AntimodeMenu { return ( <div className="button-dropdown-wrapper"> - <button className="antimodeMenu-button" title="" onPointerDown={onColorClick}><FontAwesomeIcon icon="palette" size="lg" /></button> + <button className="antimodeMenu-button color-preview-button" title="" onPointerDown={onColorClick}> + <FontAwesomeIcon icon="palette" size="lg" /> + <div className="color-preview" style={{ backgroundColor: this.activeFontColor }}></div> + </button> <button className="dropdown-button antimodeMenu-button" onPointerDown={onDropdownClick}><FontAwesomeIcon icon="caret-down" size="sm" /></button> {this.showColorDropdown ? (<div className="dropdown"> - {colors.map(color => { - if (color) return <button style={{ backgroundColor: color }} onPointerDown={e => changeColor(e, color)}></button>; - })} + <p>Change font color:</p> + <div className="color-wrapper"> + {colors.map(color => { + if (color) { + return this.activeFontColor === color ? + <button className="color-button active" style={{ backgroundColor: color }} onPointerDown={e => changeColor(e, color)}></button> : + <button className="color-button" style={{ backgroundColor: color }} onPointerDown={e => changeColor(e, color)}></button>; + } + })} + </div> </div>) : <></>} </div> @@ -459,13 +465,23 @@ export default class RichTextMenu extends AntimodeMenu { return ( <div className="button-dropdown-wrapper"> - <button className="antimodeMenu-button" title="" onPointerDown={onHighlightClick}><FontAwesomeIcon icon="highlighter" size="lg" /></button> + <button className="antimodeMenu-button color-preview-button" title="" onPointerDown={onHighlightClick}> + <FontAwesomeIcon icon="highlighter" size="lg" /> + <div className="color-preview" style={{ backgroundColor: this.activeHighlightColor }}></div> + </button> <button className="dropdown-button antimodeMenu-button" onPointerDown={onDropdownClick}><FontAwesomeIcon icon="caret-down" size="sm" /></button> {this.showHighlightDropdown ? (<div className="dropdown"> - {colors.map(color => { - if (color) return <button style={{ backgroundColor: color }} onPointerDown={e => changeHighlight(e, color)}></button>; - })} + <p>Change highlight color:</p> + <div className="color-wrapper"> + {colors.map(color => { + if (color) { + return this.activeHighlightColor === color ? + <button className="color-button active" style={{ backgroundColor: color }} onPointerDown={e => changeHighlight(e, color)}>{color === "transparent" ? "X" : ""}</button> : + <button className="color-button" style={{ backgroundColor: color }} onPointerDown={e => changeHighlight(e, color)}>{color === "transparent" ? "X" : ""}</button>; + } + })} + </div> </div>) : <></>} </div> @@ -492,9 +508,6 @@ export default class RichTextMenu extends AntimodeMenu { self.setCurrentLink(e.target.value); } - // const targetTitle = this.getTextLinkTargetTitle(); - console.log("link curr is ", this.currentLink); - // // this.setCurrentLink(targetTitle); const link = this.currentLink ? this.currentLink : ""; return ( @@ -502,11 +515,12 @@ export default class RichTextMenu extends AntimodeMenu { <button className="antimodeMenu-button" title="" onPointerDown={onDropdownClick}><FontAwesomeIcon icon="link" size="lg" /></button> <button className="dropdown-button antimodeMenu-button" onPointerDown={onDropdownClick}><FontAwesomeIcon icon="caret-down" size="sm" /></button> {this.showLinkDropdown ? - (<div className="dropdown"> + (<div className="dropdown link-menu"> <p>Linked to:</p> <input value={link} placeholder="Enter URL" onChange={onLinkChange} /> - <button onPointerDown={e => this.makeLinkToURL(link, "onRight")}>Apply hyperlink</button> - <button onPointerDown={e => this.deleteLink()}>Remove link</button> + <button className="make-button" onPointerDown={e => this.makeLinkToURL(link, "onRight")}>Apply hyperlink</button> + <div className="divider"></div> + <button className="remove-button" onPointerDown={e => this.deleteLink()}>Remove link</button> </div>) : <></>} </div> @@ -634,6 +648,10 @@ export default class RichTextMenu extends AntimodeMenu { } render() { + // if (!this.isVisible) return <></>; + SelectionManager.SelectedDocuments() + // if (this.Pinned || ) + const fontSizeOptions = [ { mark: schema.marks.pFontSize.create({ fontSize: 7 }), title: "Set font size", label: "7pt", command: this.changeFontSize }, { mark: schema.marks.pFontSize.create({ fontSize: 8 }), title: "Set font size", label: "8pt", command: this.changeFontSize }, diff --git a/src/client/util/SelectionManager.ts b/src/client/util/SelectionManager.ts index 0c733ac47..86a7a620e 100644 --- a/src/client/util/SelectionManager.ts +++ b/src/client/util/SelectionManager.ts @@ -3,6 +3,8 @@ import { Doc } from "../../new_fields/Doc"; import { DocumentView } from "../views/nodes/DocumentView"; import { computedFn } from "mobx-utils"; import { List } from "../../new_fields/List"; +import { DocumentDecorations } from "../views/DocumentDecorations"; +import RichTextMenu from "./RichTextMenu"; export namespace SelectionManager { @@ -14,7 +16,6 @@ export namespace SelectionManager { @action SelectDoc(docView: DocumentView, ctrlPressed: boolean): void { - console.log("select doc!!!"); // if doc is not in SelectedDocuments, add it if (!manager.SelectedDocuments.get(docView)) { if (!ctrlPressed) { diff --git a/src/client/util/TooltipTextMenu.tsx b/src/client/util/TooltipTextMenu.tsx index 33257b658..2c4d08b82 100644 --- a/src/client/util/TooltipTextMenu.tsx +++ b/src/client/util/TooltipTextMenu.tsx @@ -20,6 +20,8 @@ import { PastelSchemaPalette, DarkPastelSchemaPalette } from '../../new_fields/S const { toggleMark, setBlockType } = require("prosemirror-commands"); const { openPrompt, TextField } = require("./ProsemirrorCopy/prompt.js"); +// deprecated in favor of richtextmenu + //appears above a selection of text in a RichTextBox to give user options such as Bold, Italics, etc. export class TooltipTextMenu { public static Toolbar: HTMLDivElement | undefined; diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx index 093761f1f..799b3695c 100644 --- a/src/client/views/DocumentDecorations.tsx +++ b/src/client/views/DocumentDecorations.tsx @@ -77,11 +77,6 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> DocumentDecorations.Instance = this; this._keyinput = React.createRef(); reaction(() => SelectionManager.SelectedDocuments().slice(), docs => this.titleBlur(false)); - console.log("constructing document decorations!!!"); - } - - componentDidMount() { - console.log("mounting deocument deoctirioeon!!!!"); } @action titleChanged = (event: any) => this._accumulatedTitle = event.target.value; @@ -579,9 +574,6 @@ export class DocumentDecorations extends React.Component<{}, { value: string }> if (bounds.y > bounds.b) { bounds.y = bounds.b - (this._resizeBorderWidth + this._linkBoxHeight + this._titleHeight); } - // // RichTextMenu.Instance.jumpTo(this._lastX, this._lastY - 50); - // console.log("jump to "); - // RichTextMenu.Instance.jumpTo(500, 300); return (<div className="documentDecorations"> <div className="documentDecorations-background" style={{ width: (bounds.r - bounds.x + this._resizeBorderWidth) + "px", diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index f00a24d41..7d48a0859 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -48,6 +48,7 @@ import { CollectionFreeFormView } from '../collections/collectionFreeForm/Collec import { InkTool } from '../../../new_fields/InkField'; import { TraceMobx } from '../../../new_fields/util'; import RichTextMenu from '../../util/RichTextMenu'; +import { DocumentDecorations } from '../DocumentDecorations'; library.add(faEdit); library.add(faSmile, faTextHeight, faUpload); @@ -910,6 +911,9 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & prosediv && (prosediv.keeplocation = undefined); const pos = this._editorView?.state.selection.$from.pos || 1; keeplocation && setTimeout(() => this._editorView?.dispatch(this._editorView?.state.tr.setSelection(TextSelection.create(this._editorView.state.doc, pos)))); + + // jump rich text menu to this textbox + this._ref.current && RichTextMenu.Instance.jumpTo(this._ref.current.getBoundingClientRect().x, this._ref.current?.getBoundingClientRect().y - 70); } onPointerWheel = (e: React.WheelEvent): void => { // if a text note is not selected and scrollable, this prevents us from being able to scroll and zoom out at the same time @@ -1055,6 +1059,9 @@ export class FormattedTextBox extends DocAnnotatableComponent<(FieldViewProps & this._undoTyping = undefined; } this.doLinkOnDeselect(); + + // move the richtextmenu offscreen + if (!RichTextMenu.Instance.Pinned) RichTextMenu.Instance.jumpTo(-300, -300); } _lastTimedMark: Mark | undefined = undefined; |