From 8f7e99641f84ad15f34ba9e4a60b664ac93d2e5d Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Wed, 5 Apr 2023 17:21:26 -0400
Subject: added an arrange feature for freeform collections.  added btn width
 for linear buttons.

---
 src/client/views/nodes/button/FontIconBox.tsx | 15 +++++++++++++--
 1 file changed, 13 insertions(+), 2 deletions(-)

(limited to 'src/client/views/nodes/button/FontIconBox.tsx')

diff --git a/src/client/views/nodes/button/FontIconBox.tsx b/src/client/views/nodes/button/FontIconBox.tsx
index 28e6eaf1c..8410fda18 100644
--- a/src/client/views/nodes/button/FontIconBox.tsx
+++ b/src/client/views/nodes/button/FontIconBox.tsx
@@ -587,32 +587,43 @@ ScriptingGlobals.add(function toggleOverlay(checkResult?: boolean) {
     selected ? selected.props.CollectionFreeFormDocumentView?.().float() : console.log('[FontIconBox.tsx] toggleOverlay failed');
 });
 
-ScriptingGlobals.add(function showFreeform(attr: 'grid' | 'snap lines' | 'clusters' | 'viewAll', checkResult?: boolean) {
+ScriptingGlobals.add(function showFreeform(attr: 'grid' | 'snap lines' | 'clusters' | 'arrange' | 'viewAll', checkResult?: boolean) {
     const selected = SelectionManager.Docs().lastElement();
     // prettier-ignore
-    const map: Map<'grid' | 'snap lines' | 'clusters' | 'viewAll', { checkResult: (doc:Doc) => any; setDoc: (doc:Doc) => void;}> = new Map([
+    const map: Map<'grid' | 'snap lines' | 'clusters' | 'arrange'| 'viewAll', { undo: boolean, checkResult: (doc:Doc) => any; setDoc: (doc:Doc) => void;}> = new Map([
         ['grid', {
+            undo: false,
             checkResult: (doc:Doc) => doc._backgroundGridShow,
             setDoc: (doc:Doc) => doc._backgroundGridShow = !doc._backgroundGridShow,
         }],
         ['snap lines', {
+            undo: false,
             checkResult: (doc:Doc) => doc.showSnapLines,
             setDoc: (doc:Doc) => doc._showSnapLines = !doc._showSnapLines,
         }],
         ['viewAll', {
+            undo: false,
             checkResult: (doc:Doc) => doc._fitContentsToBox,
             setDoc: (doc:Doc) => doc._fitContentsToBox = !doc._fitContentsToBox,
         }],
         ['clusters', {
+            undo: false,
             checkResult: (doc:Doc) => doc._useClusters,
             setDoc: (doc:Doc) => doc._useClusters = !doc._useClusters,
         }],
+        ['arrange', {
+            undo: true,
+            checkResult: (doc:Doc) => doc._autoArrange,
+            setDoc: (doc:Doc) => doc._autoArrange = !doc._autoArrange,
+        }],
     ]);
 
     if (checkResult) {
         return map.get(attr)?.checkResult(selected) ? Colors.MEDIUM_BLUE : 'transparent';
     }
+    const batch = map.get(attr)?.undo ? UndoManager.StartBatch('set feature') : { 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) {
     const editorView = RichTextMenu.Instance?.TextView?.EditorView;
-- 
cgit v1.2.3-70-g09d2


From 68c6c36af823255824a6b0692e8c33618c2d7ca2 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Mon, 10 Apr 2023 11:32:44 -0400
Subject: fixed brushing of fonticon boxes with dropdowns.   made line charts
 use computed values instead of observables

---
 .../collectionFreeForm/CollectionFreeFormView.tsx  |  4 +-
 src/client/views/nodes/DataVizBox/DataVizBox.tsx   | 14 +++-
 .../views/nodes/DataVizBox/components/Chart.scss   |  2 +-
 .../nodes/DataVizBox/components/LineChart.tsx      | 89 ++++++++++++----------
 src/client/views/nodes/button/FontIconBox.tsx      | 33 ++++++--
 .../nodes/button/colorDropdown/ColorDropdown.tsx   | 57 +++++++-------
 src/fields/Doc.ts                                  |  2 +-
 7 files changed, 120 insertions(+), 81 deletions(-)

(limited to 'src/client/views/nodes/button/FontIconBox.tsx')

diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 9fe8f5f49..9d4a788db 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -664,8 +664,8 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
                     ActiveIsInkMask(),
                     {
                         title: 'ink stroke',
-                        x: B.x - ActiveInkWidth() / 2,
-                        y: B.y - ActiveInkWidth() / 2,
+                        x: B.x - (ActiveInkWidth() * this.props.ScreenToLocalTransform().Scale) / 2,
+                        y: B.y - (ActiveInkWidth() * this.props.ScreenToLocalTransform().Scale) / 2,
                         _width: B.width + ActiveInkWidth() * this.props.ScreenToLocalTransform().Scale,
                         _height: B.height + ActiveInkWidth() * this.props.ScreenToLocalTransform().Scale,
                     }
diff --git a/src/client/views/nodes/DataVizBox/DataVizBox.tsx b/src/client/views/nodes/DataVizBox/DataVizBox.tsx
index aaa8c3c53..8593c8994 100644
--- a/src/client/views/nodes/DataVizBox/DataVizBox.tsx
+++ b/src/client/views/nodes/DataVizBox/DataVizBox.tsx
@@ -1,4 +1,4 @@
-import { action, computed, observable } from 'mobx';
+import { action, computed, observable, ObservableMap, ObservableSet } from 'mobx';
 import { observer } from 'mobx-react';
 import * as React from 'react';
 import { Doc, StrListCast } from '../../../../fields/Doc';
@@ -27,7 +27,10 @@ export class DataVizBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
     // 2 ways of doing it
     // @observable private pairs: { [key: string]: number | string | undefined }[] = [];
     // @observable private pairs: { [key: string]: FieldResult }[] = [];
-    @observable pairs: { [key: string]: string }[] = [];
+    static pairSet = new ObservableMap<string, { [key: string]: string }[]>();
+    @computed.struct get pairs() {
+        return DataVizBox.pairSet.get(StrCast(this.rootDoc.fileUpload));
+    }
     private _chartRenderer: LineChart | undefined;
     // // another way would be store a schema that defines the type of data we are expecting from an imported doc
 
@@ -93,6 +96,7 @@ export class DataVizBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
         const width = this.props.PanelWidth() * 0.9;
         const height = (this.props.PanelHeight() - 32) /* height of 'change view' button */ * 0.9;
         const margin = { top: 10, right: 50, bottom: 50, left: 50 };
+        if (!this.pairs) return 'no data';
         // prettier-ignore
         switch (this.dataVizView) {
             case DataVizView.TABLE:     return <TableBox pairs={this.pairs} axes={this.axes} docView={this.props.DocumentView} selectAxes={this.selectAxes}/>;
@@ -109,8 +113,10 @@ export class DataVizBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
     }
 
     fetchData() {
+        if (DataVizBox.pairSet.has(StrCast(this.rootDoc.fileUpload))) return;
+        DataVizBox.pairSet.set(StrCast(this.rootDoc.fileUpload), []);
         fetch('/csvData?uri=' + this.dataUrl?.url.href) //
-            .then(res => res.json().then(action(res => !res.errno && (this.pairs = res))));
+            .then(res => res.json().then(action(res => !res.errno && DataVizBox.pairSet.set(StrCast(this.rootDoc.fileUpload), res))));
     }
 
     // handle changing the view using a button
@@ -121,7 +127,7 @@ export class DataVizBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
     }
 
     render() {
-        return this.pairs.length == 0 ? (
+        return !this.pairs?.length ? (
             <div>Loading...</div>
         ) : (
             <div
diff --git a/src/client/views/nodes/DataVizBox/components/Chart.scss b/src/client/views/nodes/DataVizBox/components/Chart.scss
index 56fcb1fcf..f1d09d2e7 100644
--- a/src/client/views/nodes/DataVizBox/components/Chart.scss
+++ b/src/client/views/nodes/DataVizBox/components/Chart.scss
@@ -8,7 +8,7 @@
 .selected {
     // change the color of the circle element to be red
     fill: transparent;
-    outline: lightblue solid 2px;
+    outline: red solid 2px;
     border-radius: 100%;
     position: absolute;
     transform-box: fill-box;
diff --git a/src/client/views/nodes/DataVizBox/components/LineChart.tsx b/src/client/views/nodes/DataVizBox/components/LineChart.tsx
index 308ef4cba..bc9f0be77 100644
--- a/src/client/views/nodes/DataVizBox/components/LineChart.tsx
+++ b/src/client/views/nodes/DataVizBox/components/LineChart.tsx
@@ -4,17 +4,17 @@ import * as React from 'react';
 // import d3
 import * as d3 from 'd3';
 import { Doc, DocListCast } from '../../../../../fields/Doc';
+import { Id } from '../../../../../fields/FieldSymbols';
 import { List } from '../../../../../fields/List';
 import { listSpec } from '../../../../../fields/Schema';
-import { Cast, DocCast, NumCast } from '../../../../../fields/Types';
+import { Cast, DocCast } from '../../../../../fields/Types';
 import { Docs } from '../../../../documents/Documents';
+import { DocumentManager } from '../../../../util/DocumentManager';
+import { LinkManager } from '../../../../util/LinkManager';
 import { PinProps, PresBox } from '../../trails';
+import { DataVizBox } from '../DataVizBox';
 import { createLineGenerator, drawLine, minMaxRange, scaleCreatorNumerical, xAxisCreator, xGrid, yAxisCreator, yGrid } from '../utils/D3Utils';
 import './Chart.scss';
-import { LinkManager } from '../../../../util/LinkManager';
-import { DocumentManager } from '../../../../util/DocumentManager';
-import { Id } from '../../../../../fields/FieldSymbols';
-import { DataVizBox } from '../DataVizBox';
 
 export interface DataPoint {
     x: number;
@@ -44,30 +44,44 @@ export class LineChart extends React.Component<LineChartProps> {
     private _disposers: { [key: string]: IReactionDisposer } = {};
     private _lineChartRef: React.RefObject<HTMLDivElement> = React.createRef();
     private _lineChartSvg: d3.Selection<SVGGElement, unknown, null, undefined> | undefined;
-    private _rangeVals: { xMin?: number; xMax?: number; yMin?: number; yMax?: number } = {};
     @observable _currSelected: SelectedDataPoint | undefined = undefined;
-    @observable _lineChartData: DataPoint[][] | undefined = undefined;
     // TODO: nda - some sort of mapping that keeps track of the annotated points so we can easily remove when annotations list updates
 
+    @computed get _lineChartData() {
+        if (this.props.axes.length <= 1) return [];
+        return this.props.pairs
+            ?.filter(pair => (!this.incomingLinks.length ? true : Array.from(Object.keys(pair)).some(key => pair[key] && key.startsWith('select'))))
+            .map(pair => ({ x: Number(pair[this.props.axes[0]]), y: Number(pair[this.props.axes[1]]) }))
+            .sort((a, b) => (a.x < b.x ? -1 : 1));
+    }
+    @computed get incomingLinks() {
+        return LinkManager.Instance.getAllRelatedLinks(this.props.rootDoc) // out of all links
+            .filter(link => link.anchor1 !== this.props.rootDoc) // get links where this chart doc is the target of the link
+            .map(link => DocCast(link.anchor1)); // then return the source of the link
+    }
+    @computed get incomingSelected() {
+        return this.incomingLinks // all links that are pointing to this node
+            .map(anchor => DocumentManager.Instance.getFirstDocumentView(anchor)?.ComponentView as DataVizBox) // get their data viz boxes
+            .filter(dvb => dvb)
+            .map(dvb => dvb.pairs?.filter(pair => pair['select' + dvb.rootDoc[Id]])) // get all the datapoints they have selected field set by incoming anchor
+            .lastElement();
+    }
+    @computed get rangeVals(): { xMin?: number; xMax?: number; yMin?: number; yMax?: number } {
+        return minMaxRange([this._lineChartData]);
+    }
     componentWillUnmount() {
         Array.from(Object.keys(this._disposers)).forEach(key => this._disposers[key]());
     }
     componentDidMount = () => {
-        this._disposers.chartdata = reaction(
-            () => this.props.axes.slice(),
-            axes => {
-                if (axes.length > 1) {
-                    this._lineChartData = [this.props.pairs?.map(pair => ({ x: Number(pair[this.props.axes[0]]), y: Number(pair[this.props.axes[1]]) })).sort((a, b) => (a.x < b.x ? -1 : 1))];
-                }
-            },
-            { fireImmediately: true }
-        );
         this._disposers.chartData = reaction(
-            () => ({ dataSet: this._lineChartData, axes: this.props.axes.slice(), w: this.props.width, h: this.props.height }),
-            vals => {
-                if (vals.dataSet) {
-                    this._rangeVals = minMaxRange(vals.dataSet);
-                    this.drawChart(vals.dataSet);
+            () => ({ dataSet: this._lineChartData, w: this.props.width, h: this.props.height }),
+            ({ dataSet, w, h }) => {
+                if (dataSet) {
+                    this.drawChart([dataSet], this.rangeVals, w, h);
+                    // redraw annotations when the chart data has changed, or the local or inherited selection has changed
+                    this.clearAnnotations();
+                    this._currSelected && this.drawAnnotations(Number(this._currSelected.x), Number(this._currSelected.y), true);
+                    this.incomingSelected?.forEach((pair: any) => this.drawAnnotations(Number(pair[this.props.axes[0]]), Number(pair[this.props.axes[1]])));
                 }
             },
             { fireImmediately: true }
@@ -87,18 +101,13 @@ export class LineChart extends React.Component<LineChartProps> {
         this._disposers.highlights = reaction(
             () => ({
                 selected: this._currSelected,
-                pairs: LinkManager.Instance.getAllRelatedLinks(this.props.rootDoc)
-                    .filter(link => link.anchor1 !== this.props.rootDoc) // all links that are pointing to this node
-                    .map(link => DocCast(link.anchor1)) // get the documents that are pointing to this node
-                    .map(anchor => DocumentManager.Instance.getFirstDocumentView(anchor)?.ComponentView as DataVizBox) // get their data viz boxes
-                    .filter(dvb => dvb)
-                    .map(dvb => dvb.pairs.filter(pair => pair['select' + dvb.rootDoc[Id]])) // get all the datapoints they have selected field set by incoming anchor
-                    .lastElement(),
+                incomingSelected: this.incomingSelected,
             }),
-            ({ selected, pairs }) => {
-                this.clearAnnoations();
+            ({ selected, incomingSelected }) => {
+                // redraw annotations when the chart data has changed, or the local or inherited selection has changed
+                this.clearAnnotations();
                 selected && this.drawAnnotations(Number(selected.x), Number(selected.y), true);
-                pairs.forEach(pair => this.drawAnnotations(Number(pair[this.props.axes[0]]), Number(pair[this.props.axes[1]])));
+                incomingSelected?.forEach((pair: any) => this.drawAnnotations(Number(pair[this.props.axes[0]]), Number(pair[this.props.axes[1]])));
             },
             { fireImmediately: true }
         );
@@ -106,7 +115,7 @@ export class LineChart extends React.Component<LineChartProps> {
 
     // anything that doesn't need to be recalculated should just be stored as drawCharts (i.e. computed values) and drawChart is gonna iterate over these observables and generate svgs based on that
 
-    clearAnnoations = () => {
+    clearAnnotations = () => {
         const elements = document.querySelectorAll('.datapoint');
         for (let i = 0; i < elements.length; i++) {
             const element = elements[i];
@@ -207,12 +216,12 @@ export class LineChart extends React.Component<LineChartProps> {
     }
 
     // TODO: nda - can use d3.create() to create html element instead of appending
-    drawChart = (dataSet: DataPoint[][]) => {
+    drawChart = (dataSet: DataPoint[][], rangeVals: { xMin?: number; xMax?: number; yMin?: number; yMax?: number }, width: number, height: number) => {
         // clearing tooltip and the current chart
         d3.select(this._lineChartRef.current).select('svg').remove();
         d3.select(this._lineChartRef.current).select('.tooltip').remove();
 
-        const { xMin, xMax, yMin, yMax } = this._rangeVals;
+        const { xMin, xMax, yMin, yMax } = rangeVals;
         if (xMin === undefined || xMax === undefined || yMin === undefined || yMax === undefined) {
             return;
         }
@@ -226,16 +235,16 @@ export class LineChart extends React.Component<LineChartProps> {
         const svg = (this._lineChartSvg = d3
             .select(this._lineChartRef.current)
             .append('svg')
-            .attr('width', `${this.width + margin.right + margin.left}`)
-            .attr('height', `${this.height + margin.top + margin.bottom}`)
+            .attr('width', `${width + margin.right + margin.left}`)
+            .attr('height', `${height + margin.top + margin.bottom}`)
             .append('g')
             .attr('transform', `translate(${margin.left}, ${margin.top})`));
 
         // create x and y grids
-        xGrid(svg.append('g'), this.height, xScale);
-        yGrid(svg.append('g'), this.width, yScale);
-        xAxisCreator(svg.append('g'), this.height, xScale);
-        yAxisCreator(svg.append('g'), this.width, yScale);
+        xGrid(svg.append('g'), height, xScale);
+        yGrid(svg.append('g'), width, yScale);
+        xAxisCreator(svg.append('g'), height, xScale);
+        yAxisCreator(svg.append('g'), width, yScale);
 
         // draw the plot line
         const data = dataSet[0];
diff --git a/src/client/views/nodes/button/FontIconBox.tsx b/src/client/views/nodes/button/FontIconBox.tsx
index 8410fda18..8eacfbc51 100644
--- a/src/client/views/nodes/button/FontIconBox.tsx
+++ b/src/client/views/nodes/button/FontIconBox.tsx
@@ -161,7 +161,13 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
                 </div>
             );
             return (
-                <div className={`menuButton ${this.type} ${numBtnType}`} onPointerDown={e => e.stopPropagation()} onClick={action(() => (this.rootDoc.dropDownOpen = !this.rootDoc.dropDownOpen))}>
+                <div
+                    className={`menuButton ${this.type} ${numBtnType}`}
+                    onPointerDown={e => e.stopPropagation()}
+                    onClick={action(() => {
+                        this.rootDoc.dropDownOpen = !this.rootDoc.dropDownOpen;
+                        Doc.UnBrushAllDocs();
+                    })}>
                     {checkResult}
                     {label}
                     {this.rootDoc.dropDownOpen ? dropdown : null}
@@ -198,7 +204,10 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
                             e.stopPropagation();
                             e.preventDefault();
                         }}
-                        onClick={action(() => (this.rootDoc.dropDownOpen = !this.rootDoc.dropDownOpen))}>
+                        onClick={action(() => {
+                            this.rootDoc.dropDownOpen = !this.rootDoc.dropDownOpen;
+                            Doc.UnBrushAllDocs();
+                        })}>
                         <input style={{ width: 30 }} className="button-input" type="number" value={checkResult} onChange={undoBatch(action(e => setValue(Number(e.target.value))))} />
                     </div>
                     <div className={`button`} onClick={action(e => setValue(Number(checkResult) + 1))}>
@@ -215,6 +224,7 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
                                 onClick={e => {
                                     e.stopPropagation();
                                     this.rootDoc.dropDownOpen = false;
+                                    Doc.UnBrushAllDocs();
                                 }}
                             />
                         </div>
@@ -237,7 +247,10 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
             <div
                 className={`menuButton ${this.type} ${active}`}
                 style={{ color: color, backgroundColor: backgroundColor, borderBottomLeftRadius: this.dropdown ? 0 : undefined }}
-                onClick={action(() => (this.rootDoc.dropDownOpen = !this.rootDoc.dropDownOpen))}>
+                onClick={action(() => {
+                    this.rootDoc.dropDownOpen = !this.rootDoc.dropDownOpen;
+                    Doc.UnBrushAllDocs();
+                })}>
                 {this.Icon(color)}
                 {!this.label || !FontIconBox.GetShowLabels() ? null : (
                     <div className="fontIconBox-label" style={{ color: color, backgroundColor: backgroundColor }}>
@@ -316,7 +329,14 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
             <div
                 className={`menuButton ${this.type} ${active}`}
                 style={{ backgroundColor: this.rootDoc.dropDownOpen ? Colors.MEDIUM_BLUE : backgroundColor, color: color, display: dropdown ? undefined : 'flex' }}
-                onClick={dropdown ? () => (this.rootDoc.dropDownOpen = !this.rootDoc.dropDownOpen) : undefined}>
+                onClick={
+                    dropdown
+                        ? () => {
+                              this.rootDoc.dropDownOpen = !this.rootDoc.dropDownOpen;
+                              Doc.UnBrushAllDocs();
+                          }
+                        : undefined
+                }>
                 {dropdown ? null : <FontAwesomeIcon style={{ marginLeft: 5 }} className={`fontIconBox-icon-${this.type}`} icon={icon} color={color} />}
                 <div className="menuButton-dropdown-header">{text && text[0].toUpperCase() + text.slice(1)}</div>
                 {label}
@@ -335,6 +355,7 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
                             onClick={e => {
                                 e.stopPropagation();
                                 this.rootDoc.dropDownOpen = false;
+                                Doc.UnBrushAllDocs();
                             }}
                         />
                     </div>
@@ -379,6 +400,7 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
                 style={{ color: color, borderBottomLeftRadius: this.dropdown ? 0 : undefined }}
                 onClick={action(e => {
                     this.colorPickerClosed = !this.colorPickerClosed;
+                    setTimeout(() => Doc.UnBrushAllDocs());
                     e.stopPropagation();
                 })}
                 onPointerDown={e => e.stopPropagation()}>
@@ -397,6 +419,7 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
                                 e.preventDefault();
                                 e.stopPropagation();
                                 this.colorPickerClosed = true;
+                                Doc.UnBrushAllDocs();
                             })}
                         />
                     </div>
@@ -816,7 +839,7 @@ ScriptingGlobals.add(function setInkProperty(option: 'inkMask' | 'fillColor' | '
             setMode: () => selected?.type !== DocumentType.INK && SetActiveIsInkMask(!ActiveIsInkMask()),
         }],
         ['fillColor', {
-            checkResult: () => (selected?.type === DocumentType.INK ? StrCast(selected.fillColor) : ActiveFillColor() ? Colors.MEDIUM_BLUE : 'transparent'),
+            checkResult: () => (selected?.type === DocumentType.INK ? StrCast(selected.fillColor) : ActiveFillColor() ?? "transparent"),
             setInk: (doc: Doc) => (doc.fillColor = StrCast(value)),
             setMode: () => SetActiveFillColor(StrCast(value)),
         }],
diff --git a/src/client/views/nodes/button/colorDropdown/ColorDropdown.tsx b/src/client/views/nodes/button/colorDropdown/ColorDropdown.tsx
index 7f414ddbb..74c3c563c 100644
--- a/src/client/views/nodes/button/colorDropdown/ColorDropdown.tsx
+++ b/src/client/views/nodes/button/colorDropdown/ColorDropdown.tsx
@@ -12,7 +12,7 @@ export class ColorDropdown extends Component<IButtonProps> {
         const active: string = StrCast(this.props.rootDoc.dropDownOpen);
 
         const script: string = StrCast(this.props.rootDoc.script);
-        const scriptCheck: string = script + "(undefined, true)";
+        const scriptCheck: string = script + '(undefined, true)';
         const boolResult = ScriptField.MakeScript(scriptCheck)?.script.run().result;
 
         const stroke: boolean = false;
@@ -24,24 +24,21 @@ export class ColorDropdown extends Component<IButtonProps> {
         //     strokeIcon = (<div style={{ borderRadius: "100%", width: width + '%', height: height + '%', backgroundColor: boolResult ? boolResult : "#FFFFFF" }} />);
         // }
 
-        const colorOptions: string[] = ['#D0021B', '#F5A623', '#F8E71C', '#8B572A', '#7ED321', '#417505',
-            '#9013FE', '#4A90E2', '#50E3C2', '#B8E986', '#000000', '#4A4A4A', '#9B9B9B',
-            '#FFFFFF', '#f1efeb'];
+        const colorOptions: string[] = ['#D0021B', '#F5A623', '#F8E71C', '#8B572A', '#7ED321', '#417505', '#9013FE', '#4A90E2', '#50E3C2', '#B8E986', '#000000', '#4A4A4A', '#9B9B9B', '#FFFFFF', '#f1efeb'];
 
-        const colorBox = (func: (color: ColorState) => void) => <SketchPicker
-            disableAlpha={!stroke}
-            onChange={func} color={boolResult ? boolResult : "#FFFFFF"}
-            presetColors={colorOptions} />;
-        const label = !this.props.label || !FontIconBox.GetShowLabels() ? (null) :
-            <div className="fontIconBox-label" style={{ color: this.props.color, backgroundColor: this.props.backgroundColor, position: "absolute" }}>
-                {this.props.label}
-            </div>;
+        const colorBox = (func: (color: ColorState) => void) => <SketchPicker disableAlpha={!stroke} onChange={func} color={boolResult ? boolResult : '#FFFFFF'} presetColors={colorOptions} />;
+        const label =
+            !this.props.label || !FontIconBox.GetShowLabels() ? null : (
+                <div className="fontIconBox-label" style={{ color: this.props.color, backgroundColor: this.props.backgroundColor, position: 'absolute' }}>
+                    {this.props.label}
+                </div>
+            );
 
-        const dropdownCaret = <div
-            className="menuButton-dropDown"
-            style={{ borderBottomRightRadius: active ? 0 : undefined }}>
-            <FontAwesomeIcon icon={'caret-down'} color={this.props.color} size="sm" />
-        </div>;
+        const dropdownCaret = (
+            <div className="menuButton-dropDown" style={{ borderBottomRightRadius: active ? 0 : undefined }}>
+                <FontAwesomeIcon icon={'caret-down'} color={this.props.color} size="sm" />
+            </div>
+        );
 
         const click = (value: ColorState) => {
             const hex: string = value.hex;
@@ -51,26 +48,30 @@ export class ColorDropdown extends Component<IButtonProps> {
             }
         };
         return (
-            <div className={`menuButton ${this.props.type} ${active}`}
+            <div
+                className={`menuButton ${this.props.type} ${active}`}
                 style={{ color: this.props.color, borderBottomLeftRadius: active ? 0 : undefined }}
-                onClick={() => this.props.rootDoc.dropDownOpen = !this.props.rootDoc.dropDownOpen}
+                onClick={() => (this.props.rootDoc.dropDownOpen = !this.props.rootDoc.dropDownOpen)}
                 onPointerDown={e => e.stopPropagation()}>
                 <FontAwesomeIcon className={`fontIconBox-icon-${this.props.type}`} icon={this.props.icon} color={this.props.color} />
-                <div className="colorButton-color"
-                    style={{ backgroundColor: boolResult ? boolResult : "#FFFFFF" }} />
+                <div className="colorButton-color" style={{ backgroundColor: boolResult ? boolResult : '#FFFFFF' }} />
                 {label}
                 {/* {dropdownCaret} */}
-                {this.props.rootDoc.dropDownOpen ?
+                {this.props.rootDoc.dropDownOpen ? (
                     <div>
-                        <div className="menuButton-dropdownBox"
-                            onPointerDown={e => e.stopPropagation()}
-                            onClick={e => e.stopPropagation()}>
+                        <div className="menuButton-dropdownBox" onPointerDown={e => e.stopPropagation()} onClick={e => e.stopPropagation()}>
                             {colorBox(click)}
                         </div>
-                        <div className="dropbox-background" onClick={(e) => { e.stopPropagation(); this.props.rootDoc.dropDownOpen = false; }} />
+                        <div
+                            className="dropbox-background"
+                            onClick={e => {
+                                e.stopPropagation();
+                                this.props.rootDoc.dropDownOpen = false;
+                            }}
+                        />
                     </div>
-                    : null}
+                ) : null}
             </div>
         );
     }
-}
\ No newline at end of file
+}
diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts
index e89f5db52..1db56cbdd 100644
--- a/src/fields/Doc.ts
+++ b/src/fields/Doc.ts
@@ -1394,7 +1394,7 @@ export namespace Doc {
         });
     }
     export function UnBrushAllDocs() {
-        brushManager.BrushedDoc.clear();
+        runInAction(() => brushManager.BrushedDoc.clear());
     }
 
     export function getDocTemplate(doc?: Doc) {
-- 
cgit v1.2.3-70-g09d2

