From 9d6c7f8100de3a952d20ad41ab20872737cb909e Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Sun, 27 Aug 2023 20:25:55 -0400
Subject: lots of cleanup to streamline import orderings (ie packages should
 not mutually import each other directly or via a chain).  change
 raiseWhenDragged to be keepZWhenDragged and got rid of system wide default.

---
 src/client/views/collections/TabDocView.tsx | 13 ++++++-------
 1 file changed, 6 insertions(+), 7 deletions(-)

(limited to 'src/client/views/collections/TabDocView.tsx')

diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx
index f379d09ff..f6acafa95 100644
--- a/src/client/views/collections/TabDocView.tsx
+++ b/src/client/views/collections/TabDocView.tsx
@@ -1,6 +1,6 @@
 import { IconProp } from '@fortawesome/fontawesome-svg-core';
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { Tooltip } from '@material-ui/core';
+import { Popup, Type } from 'browndash-components';
 import { clamp } from 'lodash';
 import { action, computed, IReactionDisposer, observable, ObservableSet, reaction } from 'mobx';
 import { observer } from 'mobx-react';
@@ -10,7 +10,7 @@ import { DocData, Height, Width } from '../../../fields/DocSymbols';
 import { Id } from '../../../fields/FieldSymbols';
 import { List } from '../../../fields/List';
 import { FieldId } from '../../../fields/RefField';
-import { BoolCast, Cast, DocCast, NumCast, StrCast } from '../../../fields/Types';
+import { Cast, DocCast, NumCast, StrCast } from '../../../fields/Types';
 import { emptyFunction, lightOrDark, returnEmptyDoclist, returnFalse, returnTrue, setupMoveUpEvents, simulateMouseClick, Utils } from '../../../Utils';
 import { DocServer } from '../../DocServer';
 import { CollectionViewType, DocumentType } from '../../documents/DocumentTypes';
@@ -21,9 +21,8 @@ import { SnappingManager } from '../../util/SnappingManager';
 import { Transform } from '../../util/Transform';
 import { undoable, UndoManager } from '../../util/UndoManager';
 import { DashboardView } from '../DashboardView';
-import { Colors, Shadows } from '../global/globalEnums';
+import { Colors } from '../global/globalEnums';
 import { LightboxView } from '../LightboxView';
-import { MainView } from '../MainView';
 import { DocFocusOptions, DocumentView, DocumentViewProps, OpenWhere, OpenWhereMod } from '../nodes/DocumentView';
 import { DashFieldView } from '../nodes/formattedText/DashFieldView';
 import { KeyValueBox } from '../nodes/KeyValueBox';
@@ -34,7 +33,6 @@ import { CollectionFreeFormView } from './collectionFreeForm/CollectionFreeFormV
 import { CollectionView } from './CollectionView';
 import './TabDocView.scss';
 import React = require('react');
-import { Popup, Toggle, Type } from 'browndash-components';
 const _global = (window /* browser */ || global) /* node */ as any;
 
 interface TabDocViewProps {
@@ -426,6 +424,7 @@ export class TabDocView extends React.Component<TabDocViewProps> {
     disableMinimap = () => !this._document || this._document.layout !== CollectionView.LayoutString(Doc.LayoutFieldKey(this._document)) || this._document?._type_collection !== CollectionViewType.Freeform;
     whenChildContentActiveChanges = (isActive: boolean) => (this._isAnyChildContentActive = isActive);
     isContentActive = () => this._isContentActive;
+    waitForDoubleClick = () => (DocumentView.ExploreMode ? 'never' : undefined);
     @computed get docView() {
         return !this._activated || !this._document ? null : (
             <>
@@ -441,8 +440,8 @@ export class TabDocView extends React.Component<TabDocViewProps> {
                     hideTitle={this.props.keyValue}
                     Document={this._document}
                     DataDoc={!Doc.AreProtosEqual(this._document[DocData], this._document) ? this._document[DocData] : undefined}
-                    onBrowseClick={MainView.Instance.exploreMode}
-                    waitForDoubleClickToClick={MainView.Instance.waitForDoubleClick}
+                    onBrowseClick={DocumentView.exploreMode}
+                    waitForDoubleClickToClick={this.waitForDoubleClick}
                     isContentActive={this.isContentActive}
                     isDocumentActive={returnFalse}
                     PanelWidth={this.PanelWidth}
-- 
cgit v1.2.3-70-g09d2


From a63ab5802551887f62265d420b7c5e925b5cd7d6 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Tue, 5 Sep 2023 01:26:54 -0400
Subject: added ui for specifying wehther to play a/v when following links, and
 cleaned up ui/etc for pres trails.  fixed a bunch of colors in pres
 properties.  fixed a/v anchors to be configs when not adding them to the doc,
 otherwise labels.

---
 src/client/util/DocumentManager.ts                 |   5 +-
 src/client/util/LinkFollower.ts                    |   1 +
 src/client/views/MainView.tsx                      |   2 +-
 src/client/views/PropertiesView.tsx                |  14 +-
 src/client/views/UndoStack.tsx                     |  69 ++++----
 .../collections/CollectionStackedTimeline.tsx      |   6 +-
 src/client/views/collections/TabDocView.tsx        |   6 +-
 src/client/views/nodes/AudioBox.tsx                |  28 +--
 src/client/views/nodes/DocumentView.tsx            |   1 +
 src/client/views/nodes/FontIconBox/FontIconBox.tsx |   1 -
 src/client/views/nodes/VideoBox.tsx                |  13 +-
 src/client/views/nodes/trails/PresBox.scss         |   6 -
 src/client/views/nodes/trails/PresBox.tsx          | 192 ++++++++++++++-------
 src/client/views/selectedDoc/SelectedDocView.tsx   |  61 +++----
 14 files changed, 244 insertions(+), 161 deletions(-)

(limited to 'src/client/views/collections/TabDocView.tsx')

diff --git a/src/client/util/DocumentManager.ts b/src/client/util/DocumentManager.ts
index 28ca37611..bfe0e1b48 100644
--- a/src/client/util/DocumentManager.ts
+++ b/src/client/util/DocumentManager.ts
@@ -1,9 +1,9 @@
-import { action, computed, observable, ObservableSet, observe, reaction } from 'mobx';
+import { action, computed, observable, ObservableSet, observe } from 'mobx';
 import { Doc, DocListCast, Opt } from '../../fields/Doc';
 import { AclAdmin, AclEdit, Animation } from '../../fields/DocSymbols';
 import { Id } from '../../fields/FieldSymbols';
 import { listSpec } from '../../fields/Schema';
-import { Cast, DocCast, StrCast } from '../../fields/Types';
+import { Cast, DocCast, NumCast, StrCast } from '../../fields/Types';
 import { AudioField } from '../../fields/URLField';
 import { GetEffectiveAcl } from '../../fields/util';
 import { CollectionViewType } from '../documents/DocumentTypes';
@@ -323,6 +323,7 @@ export class DocumentManager {
             if (docView.ComponentView instanceof FormattedTextBox) docView.ComponentView?.focus(viewSpec, options);
             PresBox.restoreTargetDocView(docView, viewSpec, options.zoomTime ?? 500);
             Doc.linkFollowHighlight(viewSpec ? [docView.rootDoc, viewSpec] : docView.rootDoc, undefined, options.effect);
+            if (options.playMedia) docView.ComponentView?.playFrom?.(NumCast(docView.rootDoc._layout_currentTimecode));
             if (options.playAudio) DocumentManager.playAudioAnno(docView.rootDoc);
             if (options.toggleTarget && (!options.didMove || docView.rootDoc.hidden)) docView.rootDoc.hidden = !docView.rootDoc.hidden;
             if (options.effect) docView.rootDoc[Animation] = options.effect;
diff --git a/src/client/util/LinkFollower.ts b/src/client/util/LinkFollower.ts
index b8fea340f..2fc811b09 100644
--- a/src/client/util/LinkFollower.ts
+++ b/src/client/util/LinkFollower.ts
@@ -73,6 +73,7 @@ export class LinkFollower {
                     const toggleTarget = canToggle && BoolCast(sourceDoc.followLinkToggle);
                     const options: DocFocusOptions = {
                         playAudio: BoolCast(sourceDoc.followLinkAudio),
+                        playMedia: BoolCast(sourceDoc.followLinkVideo),
                         toggleTarget,
                         noSelect: true,
                         willPan: true,
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 7ae9a374d..c8b89c1d5 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -805,7 +805,7 @@ export class MainView extends React.Component {
                         {this.dockingContent}
 
                         {this._hideUI ? null : (
-                            <div className="mainView-propertiesDragger" key="props" onPointerDown={this.onPropertiesPointerDown} style={{ background: SettingsManager.userBackgroundColor, right: this.propertiesWidth() - 1 }}>
+                            <div className="mainView-propertiesDragger" key="props" onPointerDown={this.onPropertiesPointerDown} style={{ background: SettingsManager.userVariantColor, right: this.propertiesWidth() - 1 }}>
                                 <FontAwesomeIcon icon={this.propertiesWidth() < 10 ? 'chevron-left' : 'chevron-right'} color={SettingsManager.userColor} size="sm" />
                             </div>
                         )}
diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx
index 5f9439cbc..01329b482 100644
--- a/src/client/views/PropertiesView.tsx
+++ b/src/client/views/PropertiesView.tsx
@@ -1538,6 +1538,16 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
                                 <FontAwesomeIcon className="fa-icon" icon={faAnchor as IconLookup} size="lg" />
                             </button>
                         </div>
+                        <div className="propertiesView-input inline">
+                            <p>Play Target Video</p>
+                            <button
+                                style={{ background: !this.sourceAnchor?.followLinkVideo ? '' : '#4476f7', borderRadius: 3 }}
+                                onPointerDown={e => this.toggleAnchorProp(e, 'followLinkVideo', this.sourceAnchor)}
+                                onClick={e => e.stopPropagation()}
+                                className="propertiesButton">
+                                <FontAwesomeIcon className="fa-icon" icon={faAnchor as IconLookup} size="lg" />
+                            </button>
+                        </div>
                         <div className="propertiesView-input inline">
                             <p>Zoom Text Selections</p>
                             <button
@@ -1742,12 +1752,12 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
                                         color: SettingsManager.userColor,
                                         backgroundColor: this.openPresVisibilityAndDuration ? SettingsManager.userVariantColor : SettingsManager.userBackgroundColor,
                                     }}>
-                                    &nbsp; <FontAwesomeIcon style={{ alignSelf: 'center' }} icon={'rocket'} /> &nbsp; Visibilty
+                                    &nbsp; <FontAwesomeIcon style={{ alignSelf: 'center' }} icon={'rocket'} /> &nbsp; Visibility
                                     <div className="propertiesView-presentationTrails-title-icon">
                                         <FontAwesomeIcon icon={this.openPresVisibilityAndDuration ? 'caret-down' : 'caret-right'} size="lg" />
                                     </div>
                                 </div>
-                                {this.openPresVisibilityAndDuration ? <div className="propertiesView-presentationTrails-content">{PresBox.Instance.visibiltyDurationDropdown}</div> : null}
+                                {this.openPresVisibilityAndDuration ? <div className="propertiesView-presentationTrails-content">{PresBox.Instance.visibilityDurationDropdown}</div> : null}
                             </div>
                         )}
                         {!selectedItem ? null : (
diff --git a/src/client/views/UndoStack.tsx b/src/client/views/UndoStack.tsx
index 47853b5e4..1afd5ad22 100644
--- a/src/client/views/UndoStack.tsx
+++ b/src/client/views/UndoStack.tsx
@@ -8,6 +8,7 @@ import { Doc } from '../../fields/Doc';
 import { Popup, Type, isDark } from 'browndash-components';
 import { Colors } from './global/globalEnums';
 import { SettingsManager } from '../util/SettingsManager';
+import { Tooltip } from '@mui/material';
 
 interface UndoStackProps {
     width?: number;
@@ -22,39 +23,43 @@ export class UndoStack extends React.Component<UndoStackProps> {
         const background = UndoManager.batchCounter.get() ? 'yellow' : SettingsManager.userVariantColor;
         const color = UndoManager.batchCounter.get() ? 'black' : SettingsManager.userColor;
         return this.props.inline && UndoStack.HideInline ? null : (
-            <div className="undoStack-outerContainer">
-                <Popup
-                    text="stack"
-                    color={color}
-                    background={background}
-                    placement={`top-start`}
-                    type={Type.TERT}
-                    popup={
-                        <div
-                            className="undoStack-commandsContainer"
-                            ref={r => r?.scroll({ behavior: 'auto', top: r?.scrollHeight + 20 })}
-                            style={{
-                                background,
-                                color,
-                            }}>
-                            {UndoManager.undoStackNames.map((name, i) => (
-                                <div className="undoStack-resultContainer" key={i}>
-                                    <div className="undoStack-commandString">{StrCast(name).replace(/[^\.]*\./, '')}</div>
-                                </div>
-                            ))}
-                            {Array.from(UndoManager.redoStackNames)
-                                .reverse()
-                                .map((name, i) => (
-                                    <div className="undoStack-resultContainer" key={i}>
-                                        <div className="undoStack-commandString" style={{ fontWeight: 'bold', color: SettingsManager.userBackgroundColor }}>
-                                            {StrCast(name).replace(/[^\.]*\./, '')}
+            <Tooltip title={'undo stack (if it stays yellow, undo is broken - you should reload Dash)'}>
+                <div>
+                    <div className="undoStack-outerContainer">
+                        <Popup
+                            text="stack"
+                            color={color}
+                            background={background}
+                            placement={`top-start`}
+                            type={Type.TERT}
+                            popup={
+                                <div
+                                    className="undoStack-commandsContainer"
+                                    ref={r => r?.scroll({ behavior: 'auto', top: r?.scrollHeight + 20 })}
+                                    style={{
+                                        background,
+                                        color,
+                                    }}>
+                                    {UndoManager.undoStackNames.map((name, i) => (
+                                        <div className="undoStack-resultContainer" key={i}>
+                                            <div className="undoStack-commandString">{StrCast(name).replace(/[^\.]*\./, '')}</div>
                                         </div>
-                                    </div>
-                                ))}
-                        </div>
-                    }
-                />
-            </div>
+                                    ))}
+                                    {Array.from(UndoManager.redoStackNames)
+                                        .reverse()
+                                        .map((name, i) => (
+                                            <div className="undoStack-resultContainer" key={i}>
+                                                <div className="undoStack-commandString" style={{ fontWeight: 'bold', color: SettingsManager.userBackgroundColor }}>
+                                                    {StrCast(name).replace(/[^\.]*\./, '')}
+                                                </div>
+                                            </div>
+                                        ))}
+                                </div>
+                            }
+                        />
+                    </div>
+                </div>
+            </Tooltip>
         );
     }
 }
diff --git a/src/client/views/collections/CollectionStackedTimeline.tsx b/src/client/views/collections/CollectionStackedTimeline.tsx
index d2be70577..0a5a80936 100644
--- a/src/client/views/collections/CollectionStackedTimeline.tsx
+++ b/src/client/views/collections/CollectionStackedTimeline.tsx
@@ -32,7 +32,7 @@ import './CollectionStackedTimeline.scss';
 export type CollectionStackedTimelineProps = {
     Play: () => void;
     Pause: () => void;
-    playLink: (linkDoc: Doc) => void;
+    playLink: (linkDoc: Doc, options: DocFocusOptions) => void;
     playFrom: (seekTimeInSeconds: number, endTime?: number) => void;
     playing: () => boolean;
     setTime: (time: number) => void;
@@ -677,7 +677,7 @@ interface StackedTimelineAnchorProps {
     height: number;
     toTimeline: (screen_delta: number, width: number) => number;
     styleProvider?: (doc: Opt<Doc>, props: Opt<DocumentViewProps>, property: string) => any;
-    playLink: (linkDoc: Doc) => void;
+    playLink: (linkDoc: Doc, options: DocFocusOptions) => void;
     setTime: (time: number) => void;
     startTag: string;
     endTag: string;
@@ -793,7 +793,7 @@ class StackedTimelineAnchor extends React.Component<StackedTimelineAnchorProps>
     renderInner = computedFn(function (this: StackedTimelineAnchor, mark: Doc, script: undefined | (() => ScriptField), doublescript: undefined | (() => ScriptField), screenXf: () => Transform, width: () => number, height: () => number) {
         const anchor = observable({ view: undefined as any });
         const focusFunc = (doc: Doc, options: DocFocusOptions): number | undefined => {
-            this.props.playLink(mark);
+            this.props.playLink(mark, options);
             return undefined;
         };
         return {
diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx
index f6acafa95..6cdb84dea 100644
--- a/src/client/views/collections/TabDocView.tsx
+++ b/src/client/views/collections/TabDocView.tsx
@@ -278,10 +278,8 @@ export class TabDocView extends React.Component<TabDocViewProps> {
 
             if (pinProps.pinViewport) PresBox.pinDocView(pinDoc, pinProps, anchorDoc ?? doc);
             if (!pinProps?.audioRange && duration !== undefined) {
-                pinDoc.mediaStart = 'manual';
-                pinDoc.mediaStop = 'manual';
-                pinDoc.config_clipStart = NumCast(doc.clipStart);
-                pinDoc.config_clipEnd = NumCast(doc.clipEnd, duration);
+                pinDoc.presentation_mediaStart = 'manual';
+                pinDoc.presentation_mediaStop = 'manual';
             }
             if (pinProps?.activeFrame !== undefined) {
                 pinDoc.config_activeFrame = pinProps?.activeFrame;
diff --git a/src/client/views/nodes/AudioBox.tsx b/src/client/views/nodes/AudioBox.tsx
index 7c409c38c..50b2432d2 100644
--- a/src/client/views/nodes/AudioBox.tsx
+++ b/src/client/views/nodes/AudioBox.tsx
@@ -8,7 +8,7 @@ import { ComputedField } from '../../../fields/ScriptField';
 import { Cast, DateCast, NumCast } from '../../../fields/Types';
 import { AudioField, nullAudio } from '../../../fields/URLField';
 import { emptyFunction, formatTime, returnFalse, setupMoveUpEvents } from '../../../Utils';
-import { DocUtils } from '../../documents/Documents';
+import { Docs, DocUtils } from '../../documents/Documents';
 import { Networking } from '../../Network';
 import { DragManager } from '../../util/DragManager';
 import { LinkManager } from '../../util/LinkManager';
@@ -20,6 +20,7 @@ import { ViewBoxAnnotatableComponent, ViewBoxAnnotatableProps } from '../DocComp
 import './AudioBox.scss';
 import { FieldView, FieldViewProps } from './FieldView';
 import { PinProps, PresBox } from './trails';
+import { DocFocusOptions } from './DocumentView';
 
 /**
  * AudioBox
@@ -134,16 +135,19 @@ export class AudioBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
     }
 
     getAnchor = (addAsAnnotation: boolean, pinProps?: PinProps) => {
-        const anchor =
-            CollectionStackedTimeline.createAnchor(
-                this.rootDoc,
-                this.dataDoc,
-                this.annotationKey,
-                this._ele?.currentTime || Cast(this.props.Document._layout_currentTimecode, 'number', null) || (this.mediaState === media_state.Recording ? (Date.now() - (this.recordingStart || 0)) / 1000 : undefined),
-                undefined,
-                undefined,
-                addAsAnnotation
-            ) || this.rootDoc;
+        const timecode = Cast(this.layoutDoc._layout_currentTimecode, 'number', null);
+        const anchor = addAsAnnotation
+            ? CollectionStackedTimeline.createAnchor(
+                  this.rootDoc,
+                  this.dataDoc,
+                  this.annotationKey,
+                  this._ele?.currentTime || Cast(this.props.Document._layout_currentTimecode, 'number', null) || (this.mediaState === media_state.Recording ? (Date.now() - (this.recordingStart || 0)) / 1000 : undefined),
+                  undefined,
+                  undefined,
+                  addAsAnnotation
+              ) || this.rootDoc
+            : Docs.Create.ConfigDocument({ title: '#' + timecode, _timecodeToShow: timecode, annotationOn: this.rootDoc });
+
         PresBox.pinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: { ...(pinProps?.pinData ?? {}), temporal: true } }, this.rootDoc);
         return anchor;
     };
@@ -418,7 +422,7 @@ export class AudioBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
     };
 
     // plays link
-    playLink = (link: Doc) => {
+    playLink = (link: Doc, options: DocFocusOptions) => {
         if (link.annotationOn === this.rootDoc) {
             if (!this.layoutDoc.dontAutoPlayFollowedLinks) {
                 this.playFrom(this.timeline?.anchorStart(link) || 0, this.timeline?.anchorEnd(link));
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 998024cea..f7773ff18 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -100,6 +100,7 @@ export interface DocFocusOptions {
     effect?: Doc; // animation effect for focus
     noSelect?: boolean; // whether target should be selected after focusing
     playAudio?: boolean; // whether to play audio annotation on focus
+    playMedia?: boolean; // whether to play start target videos
     openLocation?: OpenWhere; // where to open a missing document
     zoomTextSelections?: boolean; // whether to display a zoomed overlay of anchor text selections
     toggleTarget?: boolean; // whether to toggle target on and off
diff --git a/src/client/views/nodes/FontIconBox/FontIconBox.tsx b/src/client/views/nodes/FontIconBox/FontIconBox.tsx
index ea7c2de82..1eb6fd51c 100644
--- a/src/client/views/nodes/FontIconBox/FontIconBox.tsx
+++ b/src/client/views/nodes/FontIconBox/FontIconBox.tsx
@@ -19,7 +19,6 @@ import { SelectedDocView } from '../../selectedDoc';
 import { StyleProp } from '../../StyleProvider';
 import { OpenWhere } from '../DocumentView';
 import { FieldView, FieldViewProps } from '../FieldView';
-import { RichTextMenu } from '../formattedText/RichTextMenu';
 import './FontIconBox.scss';
 import TrailsIcon from './TrailsIcon';
 
diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx
index 56508abf6..9d9aa8a4b 100644
--- a/src/client/views/nodes/VideoBox.tsx
+++ b/src/client/views/nodes/VideoBox.tsx
@@ -29,7 +29,7 @@ import { ViewBoxAnnotatableComponent, ViewBoxAnnotatableProps } from '../DocComp
 import { MarqueeAnnotator } from '../MarqueeAnnotator';
 import { AnchorMenu } from '../pdf/AnchorMenu';
 import { StyleProp } from '../StyleProvider';
-import { DocumentView, OpenWhere } from './DocumentView';
+import { DocFocusOptions, DocumentView, OpenWhere } from './DocumentView';
 import { FieldView, FieldViewProps } from './FieldView';
 import { RecordingBox } from './RecordingBox';
 import { PinProps, PresBox } from './trails';
@@ -385,7 +385,9 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
         const timecode = Cast(this.layoutDoc._layout_currentTimecode, 'number', null);
         const marquee = AnchorMenu.Instance.GetAnchor?.(undefined, addAsAnnotation);
         if (!addAsAnnotation && marquee) marquee.backgroundColor = 'transparent';
-        const anchor = CollectionStackedTimeline.createAnchor(this.rootDoc, this.dataDoc, this.annotationKey, timecode ? timecode : undefined, undefined, marquee, addAsAnnotation) || this.rootDoc;
+        const anchor = addAsAnnotation
+            ? CollectionStackedTimeline.createAnchor(this.rootDoc, this.dataDoc, this.annotationKey, timecode ? timecode : undefined, undefined, marquee, addAsAnnotation) || this.rootDoc
+            : Docs.Create.ConfigDocument({ title: '#' + timecode, _timecodeToShow: timecode, annotationOn: this.rootDoc });
         PresBox.pinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: { ...(pinProps?.pinData ?? {}), temporal: true } }, this.rootDoc);
         return anchor;
     };
@@ -846,11 +848,11 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
     zoom = (zoom: number) => this.timeline?.setZoom(zoom);
 
     // plays link
-    playLink = (doc: Doc) => {
-        const startTime = Math.max(0, this._stackedTimeline?.anchorStart(doc) || 0);
+    playLink = (doc: Doc, options: DocFocusOptions) => {
+        const startTime = Math.max(0, NumCast(doc.config_clipStart, this._stackedTimeline?.anchorStart(doc) || 0));
         const endTime = this.timeline?.anchorEnd(doc);
         if (startTime !== undefined) {
-            if (!this.layoutDoc.dontAutoPlayFollowedLinks) endTime ? this.playFrom(startTime, endTime) : this.playFrom(startTime);
+            if (options.playMedia) endTime ? this.playFrom(startTime, endTime) : this.playFrom(startTime);
             else this.Seek(startTime);
         }
     };
@@ -1038,7 +1040,6 @@ export class VideoBox extends ViewBoxAnnotatableComponent<ViewBoxAnnotatableProp
         this.props.bringToFront(cropping);
         return cropping;
     };
-
     savedAnnotations = () => this._savedAnnotations;
     render() {
         const borderRad = this.props.styleProvider?.(this.layoutDoc, this.props, StyleProp.BorderRounding);
diff --git a/src/client/views/nodes/trails/PresBox.scss b/src/client/views/nodes/trails/PresBox.scss
index bf56b4d9e..31a003144 100644
--- a/src/client/views/nodes/trails/PresBox.scss
+++ b/src/client/views/nodes/trails/PresBox.scss
@@ -187,9 +187,6 @@
         font-size: 11;
         font-weight: 200;
         height: 20;
-        background-color: $white;
-        color: $black;
-        border: solid 1px $black;
         display: flex;
         margin-left: 5px;
         margin-top: 5px;
@@ -210,13 +207,11 @@
 
         .ribbon-propertyUpDownItem {
             cursor: pointer;
-            color: white;
             display: flex;
             justify-content: center;
             align-items: center;
             height: 100%;
             width: 100%;
-            background: $black;
         }
 
         .ribbon-propertyUpDownItem:hover {
@@ -609,7 +604,6 @@
         font-weight: 200;
         height: 20;
         background-color: $white;
-        border: solid 1px rgba(0, 0, 0, 0.5);
         display: flex;
         color: $black;
         margin-top: 5px;
diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx
index 92c130ea1..48f376075 100644
--- a/src/client/views/nodes/trails/PresBox.tsx
+++ b/src/client/views/nodes/trails/PresBox.tsx
@@ -391,11 +391,11 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
             if (from?.mediaStopTriggerList && this.layoutDoc.presentation_status !== PresStatus.Edit) {
                 DocListCast(from.mediaStopTriggerList).forEach(this.stopTempMedia);
             }
-            if (from?.mediaStop === 'auto' && this.layoutDoc.presentation_status !== PresStatus.Edit) {
+            if (from?.presentation_mediaStop === 'auto' && this.layoutDoc.presentation_status !== PresStatus.Edit) {
                 this.stopTempMedia(from.presentation_targetDoc);
             }
             // If next slide is audio / video 'Play automatically' then the next slide should be played
-            if (this.layoutDoc.presentation_status !== PresStatus.Edit && (this.targetDoc.type === DocumentType.AUDIO || this.targetDoc.type === DocumentType.VID) && this.activeItem.mediaStart === 'auto') {
+            if (this.layoutDoc.presentation_status !== PresStatus.Edit && (this.targetDoc.type === DocumentType.AUDIO || this.targetDoc.type === DocumentType.VID) && this.activeItem.presentation_mediaStart === 'auto') {
                 this.startTempMedia(this.targetDoc, this.activeItem);
             }
             if (!group) this.clearSelectedArray();
@@ -798,8 +798,9 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
             easeFunc: StrCast(activeItem.presEaseFunc, 'ease') as any,
             zoomTextSelections: BoolCast(activeItem.presentation_zoomText),
             playAudio: BoolCast(activeItem.presPlayAudio),
+            playMedia: activeItem.presentation_mediaStart === 'auto',
         };
-        if (activeItem.presOpenInLightbox) {
+        if (activeItem.presentation_openInLightbox) {
             const context = DocCast(targetDoc.annotationOn) ?? targetDoc;
             if (!DocumentManager.Instance.getLightboxDocumentView(context)) {
                 LightboxView.SetLightboxDoc(context);
@@ -1075,8 +1076,6 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
             if (doc.type === DocumentType.LABEL) {
                 const audio = Cast(doc.annotationOn, Doc, null);
                 if (audio) {
-                    audio.mediaStart = 'manual';
-                    audio.mediaStop = 'manual';
                     audio.config_clipStart = NumCast(doc._timecodeToShow /* audioStart */, NumCast(doc._timecodeToShow /* videoStart */));
                     audio.config_clipEnd = NumCast(doc._timecodeToHide /* audioEnd */, NumCast(doc._timecodeToHide /* videoEnd */));
                     audio.presentation_duration = audio.config_clipStart - audio.config_clipEnd;
@@ -1472,8 +1471,8 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
     @undoBatch
     @action
     updateOpenDoc = (activeItem: Doc) => {
-        activeItem.presOpenInLightbox = !activeItem.presOpenInLightbox;
-        this.selectedArray.forEach(doc => (doc.presOpenInLightbox = activeItem.presOpenInLightbox));
+        activeItem.presentation_openInLightbox = !activeItem.presentation_openInLightbox;
+        this.selectedArray.forEach(doc => (doc.presentation_openInLightbox = activeItem.presentation_openInLightbox));
     };
 
     @undoBatch
@@ -1501,7 +1500,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                 max={max}
                 value={value}
                 readOnly={true}
-                style={{ marginLeft: hmargin, marginRight: hmargin, width: `calc(100% - ${2 * (hmargin ?? 0)}px)` }}
+                style={{ marginLeft: hmargin, marginRight: hmargin, width: `calc(100% - ${2 * (hmargin ?? 0)}px)`, background: SettingsManager.userColor, color: SettingsManager.userVariantColor }}
                 className={`toolbar-slider ${active ? '' : 'none'}`}
                 onPointerDown={e => {
                     PresBox._sliderBatch = UndoManager.StartBatch('pres slider');
@@ -1532,7 +1531,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
         });
     };
 
-    @computed get visibiltyDurationDropdown() {
+    @computed get visibilityDurationDropdown() {
         const activeItem = this.activeItem;
         if (activeItem && this.targetDoc) {
             const targetType = this.targetDoc.type;
@@ -1541,30 +1540,49 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
             return (
                 <div className="presBox-ribbon">
                     <div className="ribbon-doubleButton">
-                        <Tooltip title={<div className="dash-tooltip">{'Hide before presented'}</div>}>
-                            <div className={`ribbon-toggle ${activeItem.presentation_hideBefore ? 'active' : ''}`} onClick={() => this.updateHideBefore(activeItem)}>
+                        <Tooltip title={<div className="dash-tooltip">Hide before presented</div>}>
+                            <div
+                                className={`ribbon-toggle ${activeItem.presentation_hideBefore ? 'active' : ''}`}
+                                style={{ border: `solid 1px ${SettingsManager.userColor}`, color: SettingsManager.userColor, background: activeItem.presentation_hideBefore ? SettingsManager.userVariantColor : SettingsManager.userBackgroundColor }}
+                                onClick={() => this.updateHideBefore(activeItem)}>
                                 Hide before
                             </div>
                         </Tooltip>
                         <Tooltip title={<div className="dash-tooltip">{'Hide while presented'}</div>}>
-                            <div className={`ribbon-toggle ${activeItem.presentation_hide ? 'active' : ''}`} onClick={() => this.updateHide(activeItem)}>
+                            <div
+                                className={`ribbon-toggle ${activeItem.presentation_hide ? 'active' : ''}`}
+                                style={{ border: `solid 1px ${SettingsManager.userColor}`, color: SettingsManager.userColor, background: activeItem.presentation_hide ? SettingsManager.userVariantColor : SettingsManager.userBackgroundColor }}
+                                onClick={() => this.updateHide(activeItem)}>
                                 Hide
                             </div>
                         </Tooltip>
 
                         <Tooltip title={<div className="dash-tooltip">{'Hide after presented'}</div>}>
-                            <div className={`ribbon-toggle ${activeItem.presentation_hideAfter ? 'active' : ''}`} onClick={() => this.updateHideAfter(activeItem)}>
+                            <div
+                                className={`ribbon-toggle ${activeItem.presentation_hideAfter ? 'active' : ''}`}
+                                style={{ border: `solid 1px ${SettingsManager.userColor}`, color: SettingsManager.userColor, background: activeItem.presentation_hideAfter ? SettingsManager.userVariantColor : SettingsManager.userBackgroundColor }}
+                                onClick={() => this.updateHideAfter(activeItem)}>
                                 Hide after
                             </div>
                         </Tooltip>
 
                         <Tooltip title={<div className="dash-tooltip">{'Open in lightbox view'}</div>}>
-                            <div className="ribbon-toggle" style={{ backgroundColor: activeItem.presOpenInLightbox ? Colors.LIGHT_BLUE : '' }} onClick={() => this.updateOpenDoc(activeItem)}>
+                            <div
+                                className="ribbon-toggle"
+                                style={{
+                                    border: `solid 1px ${SettingsManager.userColor}`,
+                                    color: SettingsManager.userColor,
+                                    background: activeItem.presentation_openInLightbox ? SettingsManager.userVariantColor : SettingsManager.userBackgroundColor,
+                                }}
+                                onClick={() => this.updateOpenDoc(activeItem)}>
                                 Lightbox
                             </div>
                         </Tooltip>
-                        <Tooltip title={<div className="dash-tooltip">{'Transition movement style'}</div>}>
-                            <div className="ribbon-toggle" onClick={() => this.updateEaseFunc(activeItem)}>
+                        <Tooltip title={<div className="dash-tooltip">Transition movement style</div>}>
+                            <div
+                                className="ribbon-toggle"
+                                style={{ border: `solid 1px ${SettingsManager.userColor}`, color: SettingsManager.userColor, background: activeItem.presEaseFunc === 'ease' ? SettingsManager.userVariantColor : SettingsManager.userBackgroundColor }}
+                                onClick={() => this.updateEaseFunc(activeItem)}>
                                 {`${StrCast(activeItem.presEaseFunc, 'ease')}`}
                             </div>
                         </Tooltip>
@@ -1573,10 +1591,10 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                         <>
                             <div className="ribbon-doubleButton">
                                 <div className="presBox-subheading">Slide Duration</div>
-                                <div className="ribbon-property">
+                                <div className="ribbon-property" style={{ border: `solid 1px ${SettingsManager.userColor}` }}>
                                     <input className="presBox-input" type="number" readOnly={true} value={duration} onKeyDown={e => e.stopPropagation()} onChange={e => this.updateDurationTime(e.target.value)} /> s
                                 </div>
-                                <div className="ribbon-propertyUpDown">
+                                <div className="ribbon-propertyUpDown" style={{ color: SettingsManager.userBackgroundColor, background: SettingsManager.userColor }}>
                                     <div className="ribbon-propertyUpDownItem" onClick={() => this.updateDurationTime(String(duration), 1000)}>
                                         <FontAwesomeIcon icon={'caret-up'} />
                                     </div>
@@ -1615,7 +1633,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                         <div className="presBox-subheading">Progressivize Collection</div>
                         <input
                             className="presBox-checkbox"
-                            style={{ margin: 10 }}
+                            style={{ margin: 10, border: `solid 1px ${SettingsManager.userColor}` }}
                             type="checkbox"
                             onChange={() => {
                                 activeItem.presentation_indexed = activeItem.presentation_indexed === undefined ? 0 : undefined;
@@ -1638,7 +1656,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                         <div className="presBox-subheading">Progressivize First Bullet</div>
                         <input
                             className="presBox-checkbox"
-                            style={{ margin: 10 }}
+                            style={{ margin: 10, border: `solid 1px ${SettingsManager.userColor}` }}
                             type="checkbox"
                             onChange={() => (activeItem.presentation_indexedStart = activeItem.presentation_indexedStart ? 0 : 1)}
                             checked={!NumCast(activeItem.presentation_indexedStart)}
@@ -1646,7 +1664,13 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                     </div>
                     <div className="ribbon-doubleButton" style={{ display: 'inline-flex' }}>
                         <div className="presBox-subheading">Expand Current Bullet</div>
-                        <input className="presBox-checkbox" style={{ margin: 10 }} type="checkbox" onChange={() => (activeItem.presBulletExpand = !activeItem.presBulletExpand)} checked={BoolCast(activeItem.presBulletExpand)} />
+                        <input
+                            className="presBox-checkbox"
+                            style={{ margin: 10, border: `solid 1px ${SettingsManager.userColor}` }}
+                            type="checkbox"
+                            onChange={() => (activeItem.presBulletExpand = !activeItem.presBulletExpand)}
+                            checked={BoolCast(activeItem.presBulletExpand)}
+                        />
                     </div>
 
                     <div className="ribbon-box">
@@ -1657,10 +1681,18 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                                 e.stopPropagation();
                                 this._openBulletEffectDropdown = !this._openBulletEffectDropdown;
                             })}
-                            style={{ borderBottomLeftRadius: this._openBulletEffectDropdown ? 0 : 5, border: this._openBulletEffectDropdown ? `solid 2px ${Colors.MEDIUM_BLUE}` : 'solid 1px black' }}>
+                            style={{
+                                color: SettingsManager.userColor,
+                                background: SettingsManager.userVariantColor,
+                                borderBottomLeftRadius: this._openBulletEffectDropdown ? 0 : 5,
+                                border: this._openBulletEffectDropdown ? `solid 2px ${SettingsManager.userVariantColor}` : `solid 1px ${SettingsManager.userColor}`,
+                            }}>
                             {effect?.toString()}
                             <FontAwesomeIcon className="presBox-dropdownIcon" style={{ gridColumn: 2, color: this._openBulletEffectDropdown ? Colors.MEDIUM_BLUE : 'black' }} icon={'angle-down'} />
-                            <div className={'presBox-dropdownOptions'} style={{ display: this._openBulletEffectDropdown ? 'grid' : 'none' }} onPointerDown={e => e.stopPropagation()}>
+                            <div
+                                className={'presBox-dropdownOptions'}
+                                style={{ display: this._openBulletEffectDropdown ? 'grid' : 'none', color: SettingsManager.userColor, background: SettingsManager.userBackgroundColor }}
+                                onPointerDown={e => e.stopPropagation()}>
                                 {bulletEffect(PresEffect.None)}
                                 {bulletEffect(PresEffect.Fade)}
                                 {bulletEffect(PresEffect.Flip)}
@@ -1725,7 +1757,12 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                                 e.stopPropagation();
                                 this._openMovementDropdown = !this._openMovementDropdown;
                             })}
-                            style={{ borderBottomLeftRadius: this._openMovementDropdown ? 0 : 5, border: this._openMovementDropdown ? `solid 2px ${Colors.MEDIUM_BLUE}` : 'solid 1px black' }}>
+                            style={{
+                                color: SettingsManager.userColor,
+                                background: SettingsManager.userVariantColor,
+                                borderBottomLeftRadius: this._openMovementDropdown ? 0 : 5,
+                                border: this._openMovementDropdown ? `solid 2px ${SettingsManager.userVariantColor}` : `solid 1px ${SettingsManager.userColor}`,
+                            }}>
                             {this.movementName(activeItem)}
                             <FontAwesomeIcon className="presBox-dropdownIcon" style={{ gridColumn: 2, color: this._openMovementDropdown ? Colors.MEDIUM_BLUE : 'black' }} icon={'angle-down'} />
                             <div className={'presBox-dropdownOptions'} id={'presBoxMovementDropdown'} onPointerDown={StopEvent} style={{ display: this._openMovementDropdown ? 'grid' : 'none' }}>
@@ -1738,10 +1775,10 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                         </div>
                         <div className="ribbon-doubleButton" style={{ display: activeItem.presentation_movement === PresMovement.Zoom ? 'inline-flex' : 'none' }}>
                             <div className="presBox-subheading">Zoom (% screen filled)</div>
-                            <div className="ribbon-property">
+                            <div className="ribbon-property" style={{ border: `solid 1px ${SettingsManager.userColor}` }}>
                                 <input className="presBox-input" type="number" readOnly={true} value={zoom} onChange={e => this.updateZoom(e.target.value)} />%
                             </div>
-                            <div className="ribbon-propertyUpDown">
+                            <div className="ribbon-propertyUpDown" style={{ color: SettingsManager.userBackgroundColor, background: SettingsManager.userColor }}>
                                 <div className="ribbon-propertyUpDownItem" onClick={() => this.updateZoom(String(zoom), 0.1)}>
                                     <FontAwesomeIcon icon={'caret-up'} />
                                 </div>
@@ -1753,10 +1790,10 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                         {PresBox.inputter('0', '1', '100', zoom, activeItem.presentation_movement === PresMovement.Zoom, this.updateZoom)}
                         <div className="ribbon-doubleButton" style={{ display: 'inline-flex' }}>
                             <div className="presBox-subheading">Transition Time</div>
-                            <div className="ribbon-property">
+                            <div className="ribbon-property" style={{ border: `solid 1px ${SettingsManager.userColor}` }}>
                                 <input className="presBox-input" type="number" readOnly={true} value={transitionSpeed} onKeyDown={e => e.stopPropagation()} onChange={action(e => this.updateTransitionTime(e.target.value))} /> s
                             </div>
-                            <div className="ribbon-propertyUpDown">
+                            <div className="ribbon-propertyUpDown" style={{ color: SettingsManager.userBackgroundColor, background: SettingsManager.userColor }}>
                                 <div className="ribbon-propertyUpDownItem" onClick={() => this.updateTransitionTime(String(transitionSpeed), 1000)}>
                                     <FontAwesomeIcon icon={'caret-up'} />
                                 </div>
@@ -1776,13 +1813,19 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                         Effects
                         <div className="ribbon-doubleButton" style={{ display: 'inline-flex' }}>
                             <div className="presBox-subheading">Play Audio Annotation</div>
-                            <input className="presBox-checkbox" style={{ margin: 10 }} type="checkbox" onChange={() => (activeItem.presPlayAudio = !BoolCast(activeItem.presPlayAudio))} checked={BoolCast(activeItem.presPlayAudio)} />
+                            <input
+                                className="presBox-checkbox"
+                                style={{ margin: 10, border: `solid 1px ${SettingsManager.userColor}` }}
+                                type="checkbox"
+                                onChange={() => (activeItem.presPlayAudio = !BoolCast(activeItem.presPlayAudio))}
+                                checked={BoolCast(activeItem.presPlayAudio)}
+                            />
                         </div>
                         <div className="ribbon-doubleButton" style={{ display: 'inline-flex' }}>
                             <div className="presBox-subheading">Zoom Text Selections</div>
                             <input
                                 className="presBox-checkbox"
-                                style={{ margin: 10 }}
+                                style={{ margin: 10, border: `solid 1px ${SettingsManager.userColor}` }}
                                 type="checkbox"
                                 onChange={() => (activeItem.presentation_zoomText = !BoolCast(activeItem.presentation_zoomText))}
                                 checked={BoolCast(activeItem.presentation_zoomText)}
@@ -1794,7 +1837,12 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                                 e.stopPropagation();
                                 this._openEffectDropdown = !this._openEffectDropdown;
                             })}
-                            style={{ borderBottomLeftRadius: this._openEffectDropdown ? 0 : 5, border: this._openEffectDropdown ? `solid 2px ${Colors.MEDIUM_BLUE}` : 'solid 1px black' }}>
+                            style={{
+                                color: SettingsManager.userColor,
+                                background: SettingsManager.userVariantColor,
+                                borderBottomLeftRadius: this._openEffectDropdown ? 0 : 5,
+                                border: this._openEffectDropdown ? `solid 2px ${SettingsManager.userVariantColor}` : `solid 1px ${SettingsManager.userColor}`,
+                            }}>
                             {effect?.toString()}
                             <FontAwesomeIcon className="presBox-dropdownIcon" style={{ gridColumn: 2, color: this._openEffectDropdown ? Colors.MEDIUM_BLUE : 'black' }} icon={'angle-down'} />
                             <div className={'presBox-dropdownOptions'} id={'presBoxMovementDropdown'} style={{ display: this._openEffectDropdown ? 'grid' : 'none' }} onPointerDown={e => e.stopPropagation()}>
@@ -1808,7 +1856,9 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                         </div>
                         <div className="ribbon-doubleButton" style={{ display: effect === PresEffectDirection.None ? 'none' : 'inline-flex' }}>
                             <div className="presBox-subheading">Effect direction</div>
-                            <div className="ribbon-property">{StrCast(this.activeItem.presentation_effectDirection)}</div>
+                            <div className="ribbon-property" style={{ border: `solid 1px ${SettingsManager.userColor}` }}>
+                                {StrCast(this.activeItem.presentation_effectDirection)}
+                            </div>
                         </div>
                         <div className="effectDirection" style={{ display: effect === PresEffectDirection.None ? 'none' : 'grid', width: 40 }}>
                             {presDirection(PresEffectDirection.Left, 'angle-right', 1, 2, {})}
@@ -1830,8 +1880,10 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
     @computed get mediaOptionsDropdown() {
         const activeItem = this.activeItem;
         if (activeItem && this.targetDoc) {
-            const clipStart = NumCast(activeItem.clipStart);
-            const clipEnd = NumCast(activeItem.clipEnd, NumCast(activeItem[Doc.LayoutFieldKey(activeItem) + '_duration']));
+            const renderTarget = PresBox.targetRenderedDoc(this.activeItem);
+            const clipStart = NumCast(renderTarget.clipStart);
+            const clipEnd = NumCast(renderTarget.clipEnd, clipStart + NumCast(renderTarget[Doc.LayoutFieldKey(renderTarget) + '_duration']));
+            const config_clipEnd = NumCast(activeItem.config_clipEnd) < NumCast(activeItem.config_clipStart) ? clipEnd - clipStart : NumCast(activeItem.config_clipEnd);
             return (
                 <div className={'presBox-ribbon'} onClick={e => e.stopPropagation()} onPointerUp={e => e.stopPropagation()} onPointerDown={e => e.stopPropagation()}>
                     <div>
@@ -1842,7 +1894,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                                     <div className="slider-text" style={{ fontWeight: 500 }}>
                                         Start time (s)
                                     </div>
-                                    <div id={'startTime'} className="slider-number" style={{ backgroundColor: Colors.LIGHT_GRAY }}>
+                                    <div id="startTime" className="slider-number" style={{ color: SettingsManager.userColor, backgroundColor: SettingsManager.userBackgroundColor }}>
                                         <input
                                             className="presBox-input"
                                             style={{ textAlign: 'center', width: '100%', height: 15, fontSize: 10 }}
@@ -1850,9 +1902,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                                             readOnly={true}
                                             value={NumCast(activeItem.config_clipStart).toFixed(2)}
                                             onKeyDown={e => e.stopPropagation()}
-                                            onChange={action((e: React.ChangeEvent<HTMLInputElement>) => {
-                                                activeItem.config_clipStart = Number(e.target.value);
-                                            })}
+                                            onChange={action(e => (activeItem.config_clipStart = Number(e.target.value)))}
                                         />
                                     </div>
                                 </div>
@@ -1860,25 +1910,23 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                                     <div className="slider-text" style={{ fontWeight: 500 }}>
                                         Duration (s)
                                     </div>
-                                    <div className="slider-number" style={{ backgroundColor: Colors.LIGHT_BLUE }}>
-                                        {Math.round((NumCast(activeItem.config_clipEnd) - NumCast(activeItem.config_clipStart)) * 10) / 10}
+                                    <div className="slider-number" style={{ color: SettingsManager.userColor, backgroundColor: SettingsManager.userBackgroundColor }}>
+                                        {Math.round((config_clipEnd - NumCast(activeItem.config_clipStart)) * 10) / 10}
                                     </div>
                                 </div>
                                 <div className="slider-block">
                                     <div className="slider-text" style={{ fontWeight: 500 }}>
                                         End time (s)
                                     </div>
-                                    <div id={'endTime'} className="slider-number" style={{ backgroundColor: Colors.LIGHT_GRAY }}>
+                                    <div id="endTime" className="slider-number" style={{ color: SettingsManager.userColor, backgroundColor: SettingsManager.userBackgroundColor }}>
                                         <input
                                             className="presBox-input"
                                             onKeyDown={e => e.stopPropagation()}
                                             style={{ textAlign: 'center', width: '100%', height: 15, fontSize: 10 }}
                                             type="number"
                                             readOnly={true}
-                                            value={NumCast(activeItem.config_clipEnd).toFixed(2)}
-                                            onChange={action((e: React.ChangeEvent<HTMLInputElement>) => {
-                                                activeItem.config_clipEnd = Number(e.target.value);
-                                            })}
+                                            value={config_clipEnd.toFixed(2)}
+                                            onChange={action(e => (activeItem.config_clipEnd = Number(e.target.value)))}
                                         />
                                     </div>
                                 </div>
@@ -1889,16 +1937,15 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                                     step="0.1"
                                     min={clipStart}
                                     max={clipEnd}
-                                    value={NumCast(activeItem.config_clipEnd)}
-                                    style={{ gridColumn: 1, gridRow: 1 }}
+                                    value={config_clipEnd}
+                                    style={{ gridColumn: 1, gridRow: 1, background: SettingsManager.userColor, color: SettingsManager.userVariantColor }}
                                     className={`toolbar-slider ${'end'}`}
                                     id="toolbar-slider"
                                     onPointerDown={e => {
                                         this._batch = UndoManager.StartBatch('config_clipEnd');
                                         const endBlock = document.getElementById('endTime');
                                         if (endBlock) {
-                                            endBlock.style.color = Colors.LIGHT_GRAY;
-                                            endBlock.style.backgroundColor = Colors.MEDIUM_BLUE;
+                                            endBlock.style.backgroundColor = SettingsManager.userVariantColor;
                                         }
                                         e.stopPropagation();
                                     }}
@@ -1906,8 +1953,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                                         this._batch?.end();
                                         const endBlock = document.getElementById('endTime');
                                         if (endBlock) {
-                                            endBlock.style.color = Colors.BLACK;
-                                            endBlock.style.backgroundColor = Colors.LIGHT_GRAY;
+                                            endBlock.style.backgroundColor = SettingsManager.userBackgroundColor;
                                         }
                                     }}
                                     onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
@@ -1928,8 +1974,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                                         this._batch = UndoManager.StartBatch('config_clipStart');
                                         const startBlock = document.getElementById('startTime');
                                         if (startBlock) {
-                                            startBlock.style.color = Colors.LIGHT_GRAY;
-                                            startBlock.style.backgroundColor = Colors.MEDIUM_BLUE;
+                                            startBlock.style.backgroundColor = SettingsManager.userVariantColor;
                                         }
                                         e.stopPropagation();
                                     }}
@@ -1937,8 +1982,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                                         this._batch?.end();
                                         const startBlock = document.getElementById('startTime');
                                         if (startBlock) {
-                                            startBlock.style.color = Colors.BLACK;
-                                            startBlock.style.backgroundColor = Colors.LIGHT_GRAY;
+                                            startBlock.style.backgroundColor = SettingsManager.userBackgroundColor;
                                         }
                                     }}
                                     onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
@@ -1958,22 +2002,46 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                             <div className="presBox-subheading">Start playing:</div>
                             <div className="presBox-radioButtons">
                                 <div className="checkbox-container">
-                                    <input className="presBox-checkbox" type="checkbox" onChange={() => (activeItem.mediaStart = 'manual')} checked={activeItem.mediaStart === 'manual'} />
+                                    <input
+                                        className="presBox-checkbox"
+                                        type="checkbox"
+                                        style={{ border: `solid 1px ${SettingsManager.userColor}` }}
+                                        onChange={() => (activeItem.presentation_mediaStart = 'manual')}
+                                        checked={activeItem.presentation_mediaStart === 'manual'}
+                                    />
                                     <div>On click</div>
                                 </div>
                                 <div className="checkbox-container">
-                                    <input className="presBox-checkbox" type="checkbox" onChange={() => (activeItem.mediaStart = 'auto')} checked={activeItem.mediaStart === 'auto'} />
+                                    <input
+                                        className="presBox-checkbox"
+                                        style={{ border: `solid 1px ${SettingsManager.userColor}` }}
+                                        type="checkbox"
+                                        onChange={() => (activeItem.presentation_mediaStart = 'auto')}
+                                        checked={activeItem.presentation_mediaStart === 'auto'}
+                                    />
                                     <div>Automatically</div>
                                 </div>
                             </div>
                             <div className="presBox-subheading">Stop playing:</div>
                             <div className="presBox-radioButtons">
                                 <div className="checkbox-container">
-                                    <input className="presBox-checkbox" type="checkbox" onChange={() => (activeItem.mediaStop = 'manual')} checked={activeItem.mediaStop === 'manual'} />
-                                    <div>At audio end time</div>
+                                    <input
+                                        className="presBox-checkbox"
+                                        type="checkbox"
+                                        style={{ border: `solid 1px ${SettingsManager.userColor}` }}
+                                        onChange={() => (activeItem.presentation_mediaStop = 'manual')}
+                                        checked={activeItem.presentation_mediaStop === 'manual'}
+                                    />
+                                    <div>At media end time</div>
                                 </div>
                                 <div className="checkbox-container">
-                                    <input className="presBox-checkbox" type="checkbox" onChange={() => (activeItem.mediaStop = 'auto')} checked={activeItem.mediaStop === 'auto'} />
+                                    <input
+                                        className="presBox-checkbox"
+                                        type="checkbox"
+                                        style={{ border: `solid 1px ${SettingsManager.userColor}` }}
+                                        onChange={() => (activeItem.presentation_mediaStop = 'auto')}
+                                        checked={activeItem.presentation_mediaStop === 'auto'}
+                                    />
                                     <div>On slide change</div>
                                 </div>
                                 {/* <div className="checkbox-container">
@@ -2221,8 +2289,8 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
         const propTitle = SettingsManager.propertiesWidth > 0 ? 'Close Presentation Panel' : 'Open Presentation Panel';
         const mode = StrCast(this.rootDoc._type_collection) as CollectionViewType;
         const isMini: boolean = this.toolbarWidth <= 100;
-        const activeColor = Colors.LIGHT_BLUE;
-        const inactiveColor = Colors.WHITE;
+        const activeColor = SettingsManager.userVariantColor;
+        const inactiveColor = SettingsManager.userColor;
         return mode === CollectionViewType.Carousel3D || Doc.IsInMyOverlay(this.rootDoc) ? null : (
             <div id="toolbarContainer" className={'presBox-toolbar'}>
                 {/* <Tooltip title={<><div className="dash-tooltip">{"Add new slide"}</div></>}><div className={`toolbar-button ${this.newDocumentTools ? "active" : ""}`} onClick={action(() => this.newDocumentTools = !this.newDocumentTools)}>
diff --git a/src/client/views/selectedDoc/SelectedDocView.tsx b/src/client/views/selectedDoc/SelectedDocView.tsx
index 955a4a174..2139919e0 100644
--- a/src/client/views/selectedDoc/SelectedDocView.tsx
+++ b/src/client/views/selectedDoc/SelectedDocView.tsx
@@ -1,12 +1,14 @@
 import React = require('react');
-import { Doc } from "../../../fields/Doc";
-import { observer } from "mobx-react";
-import { computed } from "mobx";
-import { StrCast } from "../../../fields/Types";
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { Colors, ListBox } from 'browndash-components';
+import { ListBox } from 'browndash-components';
+import { computed } from 'mobx';
+import { observer } from 'mobx-react';
+import { Doc } from '../../../fields/Doc';
+import { StrCast } from '../../../fields/Types';
 import { DocumentManager } from '../../util/DocumentManager';
 import { DocFocusOptions } from '../nodes/DocumentView';
+import { emptyFunction } from '../../../Utils';
+import { SettingsManager } from '../../util/SettingsManager';
 
 export interface SelectedDocViewProps {
     selectedDocs: Doc[];
@@ -14,34 +16,33 @@ export interface SelectedDocViewProps {
 
 @observer
 export class SelectedDocView extends React.Component<SelectedDocViewProps> {
-
     @computed get selectedDocs() {
         return this.props.selectedDocs;
     }
-    
 
     render() {
-        return <div className={`selectedDocView-container`}>
-            <ListBox
-                items={this.selectedDocs.map((doc) => {
-                    const icon = Doc.toIcon(doc);
-                    const iconEle = <FontAwesomeIcon size={'1x'} icon={icon} />;
-                    const text = StrCast(doc.title)
-                    const finished = () => {
-                        
-                    };
-                    const options: DocFocusOptions = {
-                        playAudio: false,
-                    };
-                    return {
-                        text: text,
-                        val: StrCast(doc._id),
-                        icon: iconEle,
-                        onClick: () => {DocumentManager.Instance.showDocument(doc, options, finished);}
-                    }
-                })}
-                color={StrCast(Doc.UserDoc().userColor)}
-            />
-        </div>
+        return (
+            <div className="selectedDocView-container">
+                <ListBox
+                    items={this.selectedDocs.map(doc => {
+                        const options: DocFocusOptions = {
+                            playAudio: false,
+                            playMedia: false,
+                            willPan: true,
+                        };
+                        return {
+                            text: StrCast(doc.title),
+                            val: StrCast(doc._id),
+                            color: SettingsManager.userColor,
+                            background: SettingsManager.userBackgroundColor,
+                            icon: <FontAwesomeIcon size={'1x'} icon={Doc.toIcon(doc)} />,
+                            onClick: () => DocumentManager.Instance.showDocument(doc, options, emptyFunction),
+                        };
+                    })}
+                    color={SettingsManager.userColor}
+                    background={SettingsManager.userBackgroundColor}
+                />
+            </div>
+        );
     }
-}
\ No newline at end of file
+}
-- 
cgit v1.2.3-70-g09d2


From 530294ae0b4721f07ddbfdd584ed91ff07cdc5e3 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Wed, 6 Sep 2023 12:11:23 -0400
Subject: added undo for removing dashboards and add to recently closed. fixed
 link menu to open up link editor more direclty

---
 src/client/util/CurrentUserUtils.ts                |  2 +-
 src/client/util/RTFMarkup.tsx                      |  2 +-
 src/client/util/SelectionManager.ts                |  5 +-
 src/client/util/ServerStats.tsx                    |  2 +-
 src/client/views/DashboardView.tsx                 | 12 ++--
 src/client/views/MainView.tsx                      |  2 +-
 .../views/PropertiesDocBacklinksSelector.tsx       |  7 ++-
 src/client/views/PropertiesView.scss               |  6 ++
 src/client/views/PropertiesView.tsx                | 71 ++++++++++++++--------
 src/client/views/collections/TabDocView.tsx        |  4 +-
 src/client/views/linking/LinkMenuItem.tsx          | 15 +++--
 11 files changed, 81 insertions(+), 47 deletions(-)

(limited to 'src/client/views/collections/TabDocView.tsx')

diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index af0f62c0f..836160265 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -488,7 +488,7 @@ export class CurrentUserUtils {
         const contextMenuLabels = [/*"Create New Dashboard"*/]  as string[];
         const contextMenuIcons = [/*"plus"*/]  as string[];
         const childContextMenuScripts = [toggleDarkTheme, `toggleComicMode()`, `snapshotDashboard()`, `shareDashboard(self)`, 'removeDashboard(self)', 'resetDashboard(self)']; // entries must be kept in synch with childContextMenuLabels, childContextMenuIcons, and childContextMenuFilters
-        const childContextMenuFilters =  ['!IsNoviceMode()', '!IsNoviceMode()', '!IsNoviceMode()', undefined as any, undefined as any, undefined as any];// entries must be kept in synch with childContextMenuLabels, childContextMenuIcons, and childContextMenuScripts
+        const childContextMenuFilters =  ['!IsNoviceMode()', '!IsNoviceMode()', '!IsNoviceMode()', undefined as any, undefined as any, '!IsNoviceMode()'];// entries must be kept in synch with childContextMenuLabels, childContextMenuIcons, and childContextMenuScripts
         const childContextMenuLabels =  ["Toggle Dark Theme", "Toggle Comic Mode", "Snapshot Dashboard", "Share Dashboard", "Remove Dashboard", "Reset Dashboard"];// entries must be kept in synch with childContextMenuScripts, childContextMenuIcons, and childContextMenuFilters
         const childContextMenuIcons = ["chalkboard", "tv", "camera", "users", "times", "trash"]; // entries must be kept in synch with childContextMenuScripts, childContextMenuLabels, and childContextMenuFilters
         const reqdOpts:DocumentOptions = {
diff --git a/src/client/util/RTFMarkup.tsx b/src/client/util/RTFMarkup.tsx
index 78069d323..9dd14a3c3 100644
--- a/src/client/util/RTFMarkup.tsx
+++ b/src/client/util/RTFMarkup.tsx
@@ -33,7 +33,7 @@ export class RTFMarkup extends React.Component<{}> {
      */
     @computed get cheatSheet() {
         return (
-            <div style={{ background: SettingsManager.Instance?.userBackgroundColor, color: SettingsManager.Instance?.userColor, textAlign: 'initial', height: '100%' }}>
+            <div style={{ background: SettingsManager.userBackgroundColor, color: SettingsManager.userColor, textAlign: 'initial', height: '100%' }}>
                 <p>
                     <b style={{ fontSize: 'larger' }}>{`wiki:phrase`}</b>
                     {` display wikipedia page for entered text (terminate with carriage return)`}
diff --git a/src/client/util/SelectionManager.ts b/src/client/util/SelectionManager.ts
index dbf33fcf5..d0f66d124 100644
--- a/src/client/util/SelectionManager.ts
+++ b/src/client/util/SelectionManager.ts
@@ -26,9 +26,6 @@ export namespace SelectionManager {
             // if doc is not in SelectedDocuments, add it
             if (!manager.SelectedViewsMap.get(docView)) {
                 if (!ctrlPressed) {
-                    if (LinkManager.currentLink && !LinkManager.Links(docView.rootDoc).includes(LinkManager.currentLink) && docView.rootDoc !== LinkManager.currentLink) {
-                        LinkManager.currentLink = undefined;
-                    }
                     this.DeselectAll();
                 }
 
@@ -54,6 +51,8 @@ export namespace SelectionManager {
         }
         @action
         DeselectAll(): void {
+            LinkManager.currentLink = undefined;
+            LinkManager.currentLinkAnchor = undefined;
             manager.SelectedSchemaDocument = undefined;
             Array.from(manager.SelectedViewsMap.keys()).forEach(dv => dv.props.whenChildContentsActiveChanged(false));
             manager.SelectedViewsMap.clear();
diff --git a/src/client/util/ServerStats.tsx b/src/client/util/ServerStats.tsx
index 3c7c35a7e..ac9fecd5c 100644
--- a/src/client/util/ServerStats.tsx
+++ b/src/client/util/ServerStats.tsx
@@ -48,7 +48,7 @@ export class ServerStats extends React.Component<{}> {
                     display: 'flex',
                     height: 300,
                     width: 400,
-                    background: SettingsManager.Instance?.userBackgroundColor,
+                    background: SettingsManager.userBackgroundColor,
                     opacity: 0.6,
                 }}>
                 <div style={{ width: 300, height: 100, margin: 'auto', display: 'flex', flexDirection: 'column' }}>
diff --git a/src/client/views/DashboardView.tsx b/src/client/views/DashboardView.tsx
index 3ef6c0814..34c752eec 100644
--- a/src/client/views/DashboardView.tsx
+++ b/src/client/views/DashboardView.tsx
@@ -18,7 +18,7 @@ import { CollectionViewType } from '../documents/DocumentTypes';
 import { HistoryUtil } from '../util/History';
 import { ScriptingGlobals } from '../util/ScriptingGlobals';
 import { SharingManager } from '../util/SharingManager';
-import { undoBatch, UndoManager } from '../util/UndoManager';
+import { undoable, undoBatch, UndoManager } from '../util/UndoManager';
 import { CollectionDockingView } from './collections/CollectionDockingView';
 import { CollectionView } from './collections/CollectionView';
 import { ContextMenu } from './ContextMenu';
@@ -270,6 +270,7 @@ export class DashboardView extends React.Component {
     public static openDashboard = (doc: Doc | undefined, fromHistory = false) => {
         if (!doc) return false;
         Doc.AddDocToList(Doc.MyDashboards, 'data', doc);
+        Doc.RemoveDocFromList(Doc.MyRecentlyClosed, 'data', doc);
 
         // this has the side-effect of setting the main container since we're assigning the active/guest dashboard
         Doc.UserDoc() ? (Doc.ActiveDashboard = doc) : (Doc.GuestDashboard = doc);
@@ -307,9 +308,12 @@ export class DashboardView extends React.Component {
     public static removeDashboard = async (dashboard: Doc) => {
         const dashboards = await DocListCastAsync(Doc.MyDashboards.data);
         if (dashboards?.length) {
-            if (dashboard === Doc.ActiveDashboard) DashboardView.openDashboard(dashboards.find(doc => doc !== dashboard));
-            Doc.RemoveDocFromList(Doc.MyDashboards, 'data', dashboard);
-            if (!dashboards.length) Doc.ActivePage = 'home';
+            undoable(() => {
+                if (dashboard === Doc.ActiveDashboard) DashboardView.openDashboard(dashboards.find(doc => doc !== dashboard));
+                Doc.RemoveDocFromList(Doc.MyDashboards, 'data', dashboard);
+                Doc.AddDocToList(Doc.MyRecentlyClosed, 'data', dashboard, undefined, true, true);
+                if (!dashboards.length) Doc.ActivePage = 'home';
+            }, 'remove dashboard')();
         }
     };
 
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index c8b89c1d5..8adb28fe1 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -696,7 +696,7 @@ export class MainView extends React.Component {
         switch (whereFields[0]) {
             case OpenWhere.lightbox:   return LightboxView.AddDocTab(doc, location);
             case OpenWhere.close:      return CollectionDockingView.CloseSplit(doc, whereMods);
-            case OpenWhere.toggle:     return CollectionDockingView.ToggleSplit(doc, whereMods);
+            case OpenWhere.toggle:     return CollectionDockingView.ToggleSplit(doc, whereMods, undefined, "dontSelectOnActivate"); // bcz: hack!  mark the toggle so that it won't be selected on activation- this is needed so that the backlinks menu can toggle views of targets on and off without selecting them
             case OpenWhere.add:default:return CollectionDockingView.AddSplit(doc, whereMods, undefined, undefined, keyValue);
         }
     };
diff --git a/src/client/views/PropertiesDocBacklinksSelector.tsx b/src/client/views/PropertiesDocBacklinksSelector.tsx
index 91a7b3da3..2d1e46361 100644
--- a/src/client/views/PropertiesDocBacklinksSelector.tsx
+++ b/src/client/views/PropertiesDocBacklinksSelector.tsx
@@ -1,3 +1,4 @@
+import { action } from 'mobx';
 import { observer } from 'mobx-react';
 import * as React from 'react';
 import { Doc } from '../../fields/Doc';
@@ -19,16 +20,16 @@ type PropertiesDocBacklinksSelectorProps = {
 
 @observer
 export class PropertiesDocBacklinksSelector extends React.Component<PropertiesDocBacklinksSelectorProps> {
-    getOnClick = (link: Doc) => {
+    getOnClick = action((link: Doc) => {
         const linkAnchor = this.props.Document;
         const other = LinkManager.getOppositeAnchor(link, linkAnchor);
         const otherdoc = !other ? undefined : other.annotationOn && other.type !== DocumentType.RTF ? Cast(other.annotationOn, Doc, null) : other;
-
+        LinkManager.currentLink = link;
         if (otherdoc) {
             otherdoc.hidden = false;
             this.props.addDocTab(Doc.IsDataProto(otherdoc) ? Doc.MakeDelegate(otherdoc) : otherdoc, OpenWhere.toggleRight);
         }
-    };
+    });
 
     render() {
         return !SelectionManager.Views().length ? null : (
diff --git a/src/client/views/PropertiesView.scss b/src/client/views/PropertiesView.scss
index b116a622c..510defce4 100644
--- a/src/client/views/PropertiesView.scss
+++ b/src/client/views/PropertiesView.scss
@@ -26,6 +26,12 @@
         display: flex;
         flex-direction: row;
     }
+    .propertiesView-titleExtender {
+        text-overflow: ellipsis;
+        max-width: 100%;
+        white-space: pre;
+        overflow: hidden;
+    }
 
     overflow-x: hidden;
     overflow-y: auto;
diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx
index 01329b482..6f1461fea 100644
--- a/src/client/views/PropertiesView.tsx
+++ b/src/client/views/PropertiesView.tsx
@@ -3,14 +3,12 @@ import { IconLookup } from '@fortawesome/fontawesome-svg-core';
 import { faAnchor, faArrowRight, faWindowMaximize } from '@fortawesome/free-solid-svg-icons';
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import { Checkbox, Tooltip } from '@material-ui/core';
-import { Button, Colors, EditableText, IconButton, NumberInput, Size, Slider, Type } from 'browndash-components';
+import { Colors, EditableText, IconButton, NumberInput, Size, Slider, Type } from 'browndash-components';
 import { concat } from 'lodash';
-import { Lambda, action, computed, observable } from 'mobx';
+import { action, computed, IReactionDisposer, observable, reaction } from 'mobx';
 import { observer } from 'mobx-react';
 import { ColorState, SketchPicker } from 'react-color';
 import * as Icons from 'react-icons/bs'; //{BsCollectionFill, BsFillFileEarmarkImageFill} from "react-icons/bs"
-import { GrCircleInformation } from 'react-icons/gr';
-import { Utils, emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue, setupMoveUpEvents } from '../../Utils';
 import { Doc, DocListCast, Field, FieldResult, HierarchyMapping, NumListCast, Opt, ReverseHierarchyMap, StrListCast } from '../../fields/Doc';
 import { AclAdmin, DocAcl, DocData, Height, Width } from '../../fields/DocSymbols';
 import { Id } from '../../fields/FieldSymbols';
@@ -18,28 +16,29 @@ import { InkField } from '../../fields/InkField';
 import { List } from '../../fields/List';
 import { ComputedField } from '../../fields/ScriptField';
 import { Cast, DocCast, NumCast, StrCast } from '../../fields/Types';
-import { GetEffectiveAcl, SharingPermissions, normalizeEmail } from '../../fields/util';
+import { GetEffectiveAcl, normalizeEmail, SharingPermissions } from '../../fields/util';
+import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue, setupMoveUpEvents, Utils } from '../../Utils';
 import { DocumentType } from '../documents/DocumentTypes';
 import { DocumentManager } from '../util/DocumentManager';
 import { GroupManager } from '../util/GroupManager';
 import { LinkManager } from '../util/LinkManager';
 import { SelectionManager } from '../util/SelectionManager';
+import { SettingsManager } from '../util/SettingsManager';
 import { SharingManager } from '../util/SharingManager';
 import { Transform } from '../util/Transform';
-import { UndoManager, undoBatch, undoable } from '../util/UndoManager';
+import { undoable, undoBatch, UndoManager } from '../util/UndoManager';
 import { EditableView } from './EditableView';
 import { FilterPanel } from './FilterPanel';
 import { InkStrokeProperties } from './InkStrokeProperties';
+import { DocumentView, OpenWhere, StyleProviderFunc } from './nodes/DocumentView';
+import { KeyValueBox } from './nodes/KeyValueBox';
+import { PresBox, PresEffect, PresEffectDirection } from './nodes/trails';
 import { PropertiesButtons } from './PropertiesButtons';
 import { PropertiesDocBacklinksSelector } from './PropertiesDocBacklinksSelector';
 import { PropertiesDocContextSelector } from './PropertiesDocContextSelector';
 import { PropertiesSection } from './PropertiesSection';
 import './PropertiesView.scss';
 import { DefaultStyleProvider } from './StyleProvider';
-import { DocumentView, OpenWhere, StyleProviderFunc } from './nodes/DocumentView';
-import { KeyValueBox } from './nodes/KeyValueBox';
-import { PresBox, PresEffect, PresEffectDirection } from './nodes/trails';
-import { SettingsManager } from '../util/SettingsManager';
 const _global = (window /* browser */ || global) /* node */ as any;
 
 interface PropertiesViewProps {
@@ -87,13 +86,6 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
     @observable openTransform: boolean = true;
     @observable openFilters: boolean = false;
 
-    /**
-     * autorun to set up the filter doc of a collection if that collection has been selected and the filters panel is open
-     */
-    private selectedDocListenerDisposer: Opt<Lambda>;
-
-    // @observable selectedUser: string = "";
-    // @observable addButtonPressed: boolean = false;
     @observable layoutDocAcls: boolean = false;
 
     //Pres Trails booleans:
@@ -105,14 +97,21 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
 
     @observable inOptions: boolean = false;
     @observable _controlButton: boolean = false;
+    private _disposers: { [name: string]: IReactionDisposer } = {};
 
     componentDidMount() {
-        this.selectedDocListenerDisposer?.();
-        // this.selectedDocListenerDisposer = autorun(() => this.openFilters && this.selectedDoc && this.checkFilterDoc());
+        this._disposers.link = reaction(
+            () => LinkManager.currentLink,
+            link => {
+                link && this.onDoubleClick();
+                link && (this.openLinks = true);
+            },
+            { fireImmediately: true }
+        );
     }
 
     componentWillUnmount() {
-        this.selectedDocListenerDisposer?.();
+        Object.values(this._disposers).forEach(disposer => disposer?.());
     }
 
     @computed get isInk() {
@@ -555,9 +554,29 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
 
     @computed get editableTitle() {
         const titles = new Set<string>();
-        const title = Array.from(titles.keys()).length > 1 ? '--multiple selected--' : StrCast(this.selectedDoc?.title);
         SelectionManager.Views().forEach(dv => titles.add(StrCast(dv.rootDoc.title)));
-        return <EditableText val={title} setVal={this.setTitle} color={this.color} type={Type.SEC} formLabel={'Title'} fillWidth />;
+        const title = Array.from(titles.keys()).length > 1 ? '--multiple selected--' : StrCast(this.selectedDoc?.title);
+        return (
+            <div>
+                <EditableText val={title} setVal={this.setTitle} color={this.color} type={Type.SEC} formLabel={'Title'} fillWidth />
+                {LinkManager.currentLinkAnchor ? (
+                    <p className="propertiesView-titleExtender">
+                        <>
+                            <b>Anchor:</b>
+                            {LinkManager.currentLinkAnchor.title}
+                        </>
+                    </p>
+                ) : null}
+                {LinkManager.currentLink?.title ? (
+                    <p className="propertiesView-titleExtender">
+                        <>
+                            <b>Link:</b>
+                            {LinkManager.currentLink.title}
+                        </>
+                    </p>
+                ) : null}
+            </div>
+        );
     }
 
     @computed get currentType() {
@@ -1101,7 +1120,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
                 isOpen={this.openOptions}
                 setInSection={bool => (this.inOptions = bool)}
                 setIsOpen={bool => (this.openOptions = bool)}
-                onDoubleClick={() => this.onDoubleClick()}
+                onDoubleClick={this.onDoubleClick}
             />
         );
     }
@@ -1209,11 +1228,11 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
     }
 
     @computed get linksSubMenu() {
-        return <PropertiesSection title="Linked To" content={this.linkCount > 0 ? this.links : 'There are no current links.'} isOpen={this.openLinks} setIsOpen={bool => (this.openLinks = bool)} onDoubleClick={() => this.onDoubleClick()} />;
+        return <PropertiesSection title="Linked To" content={this.linkCount > 0 ? this.links : 'There are no current links.'} isOpen={this.openLinks} setIsOpen={bool => (this.openLinks = bool)} onDoubleClick={this.onDoubleClick} />;
     }
 
     @computed get layoutSubMenu() {
-        return <PropertiesSection title="Layout" content={this.layoutPreview} isOpen={this.openLayout} setIsOpen={bool => (this.openLayout = bool)} onDoubleClick={() => this.onDoubleClick()} />;
+        return <PropertiesSection title="Layout" content={this.layoutPreview} isOpen={this.openLayout} setIsOpen={bool => (this.openLayout = bool)} onDoubleClick={this.onDoubleClick} />;
     }
 
     @computed get description() {
@@ -1699,7 +1718,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
                         <div className="propertiesView-type"> {this.currentType} </div>
                         {this.optionsSubMenu}
                         {this.linksSubMenu}
-                        {!this.selectedDoc || !LinkManager.currentLink || (!hasSelectedAnchor && this.selectedDoc !== LinkManager.currentLink) ? null : this.linkProperties}
+                        {!LinkManager.currentLink || !this.openLinks ? null : this.linkProperties}
                         {this.inkSubMenu}
                         {this.contextsSubMenu}
                         {this.fieldsSubMenu}
diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx
index 6cdb84dea..9823dfe91 100644
--- a/src/client/views/collections/TabDocView.tsx
+++ b/src/client/views/collections/TabDocView.tsx
@@ -348,7 +348,7 @@ export class TabDocView extends React.Component<TabDocViewProps> {
     private onActiveContentItemChanged(contentItem: any) {
         if (!contentItem || (this.stack === contentItem.parent && ((contentItem?.tab === this.tab && !this._isActive) || (contentItem?.tab !== this.tab && this._isActive)))) {
             this._activated = this._isActive = !contentItem || contentItem?.tab === this.tab;
-            if (!this._view) setTimeout(() => SelectionManager.SelectView(this._view, false));
+            if (!this._view && this.tab?.contentItem?.config?.props?.panelName !== 'dontSelectOnActivate') setTimeout(() => SelectionManager.SelectView(this._view, false));
             !this._isActive && this._document && Doc.UnBrushDoc(this._document); // bcz: bad -- trying to simulate a pointer leave event when a new tab is opened up on top of an existing one.
         }
     }
@@ -380,7 +380,7 @@ export class TabDocView extends React.Component<TabDocViewProps> {
                                        return LightboxView.AddDocTab(doc, location);
             case OpenWhere.close:      return CollectionDockingView.CloseSplit(doc, whereMods);
             case OpenWhere.replace:    return CollectionDockingView.ReplaceTab(doc, whereMods, this.stack, undefined, keyValue);
-            case OpenWhere.toggle:     return CollectionDockingView.ToggleSplit(doc, whereMods, this.stack, undefined, keyValue);
+            case OpenWhere.toggle:     return CollectionDockingView.ToggleSplit(doc, whereMods, this.stack, "dontSelectOnActivate", keyValue);
             case OpenWhere.add:default:return CollectionDockingView.AddSplit(doc, whereMods, this.stack, undefined, keyValue);
         }
     };
diff --git a/src/client/views/linking/LinkMenuItem.tsx b/src/client/views/linking/LinkMenuItem.tsx
index 9bc8f5e8b..0a9d7543b 100644
--- a/src/client/views/linking/LinkMenuItem.tsx
+++ b/src/client/views/linking/LinkMenuItem.tsx
@@ -69,10 +69,8 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> {
         }
         return this.props.sourceDoc;
     }
-    @action
+
     onEdit = (e: React.PointerEvent) => {
-        LinkManager.currentLink = this.props.linkDoc === LinkManager.currentLink ? undefined : this.props.linkDoc;
-        LinkManager.currentLinkAnchor = this.sourceAnchor;
         setupMoveUpEvents(
             this,
             e,
@@ -90,8 +88,11 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> {
                     DocumentViewInternal.addDocTabFunc(trail, OpenWhere.replaceRight);
                 } else {
                     SelectionManager.SelectView(this.props.docView, false);
+                    LinkManager.currentLink = this.props.linkDoc === LinkManager.currentLink ? undefined : this.props.linkDoc;
+                    LinkManager.currentLinkAnchor = LinkManager.currentLink ? this.sourceAnchor : undefined;
+
                     if ((SettingsManager.propertiesWidth ?? 0) < 100) {
-                        SettingsManager.propertiesWidth = 250;
+                        setTimeout(action(() => (SettingsManager.propertiesWidth = 250)));
                     }
                 }
             })
@@ -150,7 +151,11 @@ export class LinkMenuItem extends React.Component<LinkMenuItemProps> {
                 className="linkMenu-item"
                 onPointerEnter={action(e => (this._hover = true))}
                 onPointerLeave={action(e => (this._hover = false))}
-                style={{ background: /*LinkManager.currentLink !== this.props.linkDoc*/ this._hover ? SettingsManager.userVariantColor : SettingsManager.userBackgroundColor }}>
+                style={{
+                    fontSize: this._hover ? 'larger' : undefined,
+                    fontWeight: this._hover ? 'bold' : undefined,
+                    background: LinkManager.currentLink === this.props.linkDoc ? SettingsManager.userVariantColor : SettingsManager.userBackgroundColor,
+                }}>
                 <div className="linkMenu-item-content expand-two">
                     <div
                         ref={this._drag}
-- 
cgit v1.2.3-70-g09d2


From cfe341e7bbde7a6cee745d7cee61fb0d4af2a838 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Thu, 7 Sep 2023 15:14:38 -0400
Subject: removed unused reaction in tabdoc

---
 src/client/views/collections/TabDocView.tsx | 18 +++++++++---------
 1 file changed, 9 insertions(+), 9 deletions(-)

(limited to 'src/client/views/collections/TabDocView.tsx')

diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx
index 9823dfe91..e963e2f52 100644
--- a/src/client/views/collections/TabDocView.tsx
+++ b/src/client/views/collections/TabDocView.tsx
@@ -215,15 +215,15 @@ export class TabDocView extends React.Component<TabDocViewProps> {
             );
 
             // highlight the tab when the tab document is brushed in any part of the UI
-            tab._disposers.reactionDisposer = reaction(
-                () => ({ title: doc.title, degree: Doc.IsBrushedDegree(doc) }),
-                ({ title, degree }) => {
-                    //titleEle.value = title;
-                    // titleEle.style.padding = degree ? 0 : 2;
-                    // titleEle.style.border = `${["gray", "gray", "gray"][degree]} ${["none", "dashed", "solid"][degree]} 2px`;
-                },
-                { fireImmediately: true }
-            );
+            // tab._disposers.reactionDisposer = reaction(
+            //     () => ({ title: doc.title, degree: Doc.IsBrushedDegree(doc) }),
+            //     ({ title, degree }) => {
+            //         titleEle.value = title;
+            //         titleEle.style.padding = degree ? 0 : 2;
+            //         titleEle.style.border = `${['gray', 'gray', 'gray'][degree]} ${['none', 'dashed', 'solid'][degree]} 2px`;
+            //     },
+            //     { fireImmediately: true }
+            // );
 
             // clean up the tab when it is closed
             tab.closeElement
-- 
cgit v1.2.3-70-g09d2


From fcf44ede1de94778048b8efa14e20fa265c9408d Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Thu, 7 Sep 2023 17:04:26 -0400
Subject: another popup fix

---
 package-lock.json                           | 681 +++++++++++++++-------------
 package.json                                |   2 +-
 src/client/views/collections/TabDocView.tsx |  91 ++--
 3 files changed, 400 insertions(+), 374 deletions(-)

(limited to 'src/client/views/collections/TabDocView.tsx')

diff --git a/package-lock.json b/package-lock.json
index 8ba450f51..ee930cd15 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -142,20 +142,20 @@
             "integrity": "sha512-5UamI7xkUcJ3i9qVDS+KFDEK8/7oJ55/sJMB1Ge7IEapr7KfdfV/HErR+koZwOfd+SgtFKOKRhRakdg++DcJpQ=="
         },
         "@babel/core": {
-            "version": "7.22.11",
-            "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.22.11.tgz",
-            "integrity": "sha512-lh7RJrtPdhibbxndr6/xx0w8+CVlY5FJZiaSz908Fpy+G0xkBFTvwLcKJFF4PJxVfGhVWNebikpWGnOoC71juQ==",
+            "version": "7.22.15",
+            "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.22.15.tgz",
+            "integrity": "sha512-PtZqMmgRrvj8ruoEOIwVA3yoF91O+Hgw9o7DAUTNBA6Mo2jpu31clx9a7Nz/9JznqetTR6zwfC4L3LAjKQXUwA==",
             "requires": {
                 "@ampproject/remapping": "^2.2.0",
-                "@babel/code-frame": "^7.22.10",
-                "@babel/generator": "^7.22.10",
-                "@babel/helper-compilation-targets": "^7.22.10",
-                "@babel/helper-module-transforms": "^7.22.9",
-                "@babel/helpers": "^7.22.11",
-                "@babel/parser": "^7.22.11",
-                "@babel/template": "^7.22.5",
-                "@babel/traverse": "^7.22.11",
-                "@babel/types": "^7.22.11",
+                "@babel/code-frame": "^7.22.13",
+                "@babel/generator": "^7.22.15",
+                "@babel/helper-compilation-targets": "^7.22.15",
+                "@babel/helper-module-transforms": "^7.22.15",
+                "@babel/helpers": "^7.22.15",
+                "@babel/parser": "^7.22.15",
+                "@babel/template": "^7.22.15",
+                "@babel/traverse": "^7.22.15",
+                "@babel/types": "^7.22.15",
                 "convert-source-map": "^1.7.0",
                 "debug": "^4.1.0",
                 "gensync": "^1.0.0-beta.2",
@@ -173,11 +173,11 @@
                     }
                 },
                 "@babel/generator": {
-                    "version": "7.22.10",
-                    "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.10.tgz",
-                    "integrity": "sha512-79KIf7YiWjjdZ81JnLujDRApWtl7BxTqWD88+FFdQEIOG8LJ0etDOM7CXuIgGJa55sGOwZVwuEsaLEm0PJ5/+A==",
+                    "version": "7.22.15",
+                    "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.15.tgz",
+                    "integrity": "sha512-Zu9oWARBqeVOW0dZOjXc3JObrzuqothQ3y/n1kUtrjCoCPLkXUwMvOo/F/TCfoHMbWIFlWwpZtkZVb9ga4U2pA==",
                     "requires": {
-                        "@babel/types": "^7.22.10",
+                        "@babel/types": "^7.22.15",
                         "@jridgewell/gen-mapping": "^0.3.2",
                         "@jridgewell/trace-mapping": "^0.3.17",
                         "jsesc": "^2.5.1"
@@ -194,35 +194,52 @@
                     }
                 },
                 "@babel/parser": {
-                    "version": "7.22.14",
-                    "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.14.tgz",
-                    "integrity": "sha512-1KucTHgOvaw/LzCVrEOAyXkr9rQlp0A1HiHRYnSUE9dmb8PvPW7o5sscg+5169r54n3vGlbx6GevTE/Iw/P3AQ=="
+                    "version": "7.22.16",
+                    "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.16.tgz",
+                    "integrity": "sha512-+gPfKv8UWeKKeJTUxe59+OobVcrYHETCsORl61EmSkmgymguYk/X5bp7GuUIXaFsc6y++v8ZxPsLSSuujqDphA=="
+                },
+                "@babel/template": {
+                    "version": "7.22.15",
+                    "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz",
+                    "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==",
+                    "requires": {
+                        "@babel/code-frame": "^7.22.13",
+                        "@babel/parser": "^7.22.15",
+                        "@babel/types": "^7.22.15"
+                    }
                 },
                 "@babel/traverse": {
-                    "version": "7.22.11",
-                    "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.11.tgz",
-                    "integrity": "sha512-mzAenteTfomcB7mfPtyi+4oe5BZ6MXxWcn4CX+h4IRJ+OOGXBrWU6jDQavkQI9Vuc5P+donFabBfFCcmWka9lQ==",
+                    "version": "7.22.15",
+                    "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.15.tgz",
+                    "integrity": "sha512-DdHPwvJY0sEeN4xJU5uRLmZjgMMDIvMPniLuYzUVXj/GGzysPl0/fwt44JBkyUIzGJPV8QgHMcQdQ34XFuKTYQ==",
                     "requires": {
-                        "@babel/code-frame": "^7.22.10",
-                        "@babel/generator": "^7.22.10",
+                        "@babel/code-frame": "^7.22.13",
+                        "@babel/generator": "^7.22.15",
                         "@babel/helper-environment-visitor": "^7.22.5",
                         "@babel/helper-function-name": "^7.22.5",
                         "@babel/helper-hoist-variables": "^7.22.5",
                         "@babel/helper-split-export-declaration": "^7.22.6",
-                        "@babel/parser": "^7.22.11",
-                        "@babel/types": "^7.22.11",
+                        "@babel/parser": "^7.22.15",
+                        "@babel/types": "^7.22.15",
                         "debug": "^4.1.0",
                         "globals": "^11.1.0"
                     }
                 },
                 "@babel/types": {
-                    "version": "7.22.11",
-                    "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.11.tgz",
-                    "integrity": "sha512-siazHiGuZRz9aB9NpHy9GOs9xiQPKnMzgdr493iI1M67vRXpnEq8ZOOKzezC5q7zwuQ6sDhdSp4SD9ixKSqKZg==",
+                    "version": "7.22.15",
+                    "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.15.tgz",
+                    "integrity": "sha512-X+NLXr0N8XXmN5ZsaQdm9U2SSC3UbIYq/doL++sueHOTisgZHoKaQtZxGuV2cUPQHMfjKEfg/g6oy7Hm6SKFtA==",
                     "requires": {
                         "@babel/helper-string-parser": "^7.22.5",
-                        "@babel/helper-validator-identifier": "^7.22.5",
+                        "@babel/helper-validator-identifier": "^7.22.15",
                         "to-fast-properties": "^2.0.0"
+                    },
+                    "dependencies": {
+                        "@babel/helper-validator-identifier": {
+                            "version": "7.22.15",
+                            "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.15.tgz",
+                            "integrity": "sha512-4E/F9IIEi8WR94324mbDUMo074YTheJmd7eZF5vITTeYchqAi6sYXRLHUVsmkdmY4QjfKTcB2jB7dVP3NaBElQ=="
+                        }
                     }
                 },
                 "debug": {
@@ -270,32 +287,37 @@
             }
         },
         "@babel/helper-builder-binary-assignment-operator-visitor": {
-            "version": "7.22.10",
-            "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.22.10.tgz",
-            "integrity": "sha512-Av0qubwDQxC56DoUReVDeLfMEjYYSN1nZrTUrWkXd7hpU73ymRANkbuDm3yni9npkn+RXy9nNbEJZEzXr7xrfQ==",
+            "version": "7.22.15",
+            "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.22.15.tgz",
+            "integrity": "sha512-QkBXwGgaoC2GtGZRoma6kv7Szfv06khvhFav67ZExau2RaXzy8MpHSMO2PNoP2XtmQphJQRHFfg77Bq731Yizw==",
             "requires": {
-                "@babel/types": "^7.22.10"
+                "@babel/types": "^7.22.15"
             },
             "dependencies": {
+                "@babel/helper-validator-identifier": {
+                    "version": "7.22.15",
+                    "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.15.tgz",
+                    "integrity": "sha512-4E/F9IIEi8WR94324mbDUMo074YTheJmd7eZF5vITTeYchqAi6sYXRLHUVsmkdmY4QjfKTcB2jB7dVP3NaBElQ=="
+                },
                 "@babel/types": {
-                    "version": "7.22.11",
-                    "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.11.tgz",
-                    "integrity": "sha512-siazHiGuZRz9aB9NpHy9GOs9xiQPKnMzgdr493iI1M67vRXpnEq8ZOOKzezC5q7zwuQ6sDhdSp4SD9ixKSqKZg==",
+                    "version": "7.22.15",
+                    "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.15.tgz",
+                    "integrity": "sha512-X+NLXr0N8XXmN5ZsaQdm9U2SSC3UbIYq/doL++sueHOTisgZHoKaQtZxGuV2cUPQHMfjKEfg/g6oy7Hm6SKFtA==",
                     "requires": {
                         "@babel/helper-string-parser": "^7.22.5",
-                        "@babel/helper-validator-identifier": "^7.22.5",
+                        "@babel/helper-validator-identifier": "^7.22.15",
                         "to-fast-properties": "^2.0.0"
                     }
                 }
             }
         },
         "@babel/helper-compilation-targets": {
-            "version": "7.22.10",
-            "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.10.tgz",
-            "integrity": "sha512-JMSwHD4J7SLod0idLq5PKgI+6g/hLD/iuWBq08ZX49xE14VpVEojJ5rHWptpirV2j020MvypRLAXAO50igCJ5Q==",
+            "version": "7.22.15",
+            "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.15.tgz",
+            "integrity": "sha512-y6EEzULok0Qvz8yyLkCvVX+02ic+By2UdOhylwUOvOn9dvYc9mKICJuuU1n1XBI02YWsNsnrY1kc6DVbjcXbtw==",
             "requires": {
                 "@babel/compat-data": "^7.22.9",
-                "@babel/helper-validator-option": "^7.22.5",
+                "@babel/helper-validator-option": "^7.22.15",
                 "browserslist": "^4.21.9",
                 "lru-cache": "^5.1.1",
                 "semver": "^6.3.1"
@@ -322,14 +344,14 @@
             }
         },
         "@babel/helper-create-class-features-plugin": {
-            "version": "7.22.11",
-            "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.22.11.tgz",
-            "integrity": "sha512-y1grdYL4WzmUDBRGK0pDbIoFd7UZKoDurDzWEoNMYoj1EL+foGRQNyPWDcC+YyegN5y1DUsFFmzjGijB3nSVAQ==",
+            "version": "7.22.15",
+            "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.22.15.tgz",
+            "integrity": "sha512-jKkwA59IXcvSaiK2UN45kKwSC9o+KuoXsBDvHvU/7BecYIp8GQ2UwrVvFgJASUT+hBnwJx6MhvMCuMzwZZ7jlg==",
             "requires": {
                 "@babel/helper-annotate-as-pure": "^7.22.5",
                 "@babel/helper-environment-visitor": "^7.22.5",
                 "@babel/helper-function-name": "^7.22.5",
-                "@babel/helper-member-expression-to-functions": "^7.22.5",
+                "@babel/helper-member-expression-to-functions": "^7.22.15",
                 "@babel/helper-optimise-call-expression": "^7.22.5",
                 "@babel/helper-replace-supers": "^7.22.9",
                 "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5",
@@ -353,9 +375,9 @@
             }
         },
         "@babel/helper-create-regexp-features-plugin": {
-            "version": "7.22.9",
-            "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.22.9.tgz",
-            "integrity": "sha512-+svjVa/tFwsNSG4NEy1h85+HQ5imbT92Q5/bgtS7P0GTQlP8WuFdqsiABmQouhiFGyV66oGxZFpeYHza1rNsKw==",
+            "version": "7.22.15",
+            "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.22.15.tgz",
+            "integrity": "sha512-29FkPLFjn4TPEa3RE7GpW+qbE8tlsu3jntNYNfcGsc49LphF1PQIiD+vMZ1z1xVOKt+93khA9tc2JBs3kBjA7w==",
             "requires": {
                 "@babel/helper-annotate-as-pure": "^7.22.5",
                 "regexpu-core": "^5.3.1",
@@ -437,11 +459,28 @@
             }
         },
         "@babel/helper-member-expression-to-functions": {
-            "version": "7.22.5",
-            "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.22.5.tgz",
-            "integrity": "sha512-aBiH1NKMG0H2cGZqspNvsaBe6wNGjbJjuLy29aU+eDZjSbbN53BaxlpB02xm9v34pLTZ1nIQPFYn2qMZoa5BQQ==",
+            "version": "7.22.15",
+            "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.22.15.tgz",
+            "integrity": "sha512-qLNsZbgrNh0fDQBCPocSL8guki1hcPvltGDv/NxvUoABwFq7GkKSu1nRXeJkVZc+wJvne2E0RKQz+2SQrz6eAA==",
             "requires": {
-                "@babel/types": "^7.22.5"
+                "@babel/types": "^7.22.15"
+            },
+            "dependencies": {
+                "@babel/helper-validator-identifier": {
+                    "version": "7.22.15",
+                    "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.15.tgz",
+                    "integrity": "sha512-4E/F9IIEi8WR94324mbDUMo074YTheJmd7eZF5vITTeYchqAi6sYXRLHUVsmkdmY4QjfKTcB2jB7dVP3NaBElQ=="
+                },
+                "@babel/types": {
+                    "version": "7.22.15",
+                    "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.15.tgz",
+                    "integrity": "sha512-X+NLXr0N8XXmN5ZsaQdm9U2SSC3UbIYq/doL++sueHOTisgZHoKaQtZxGuV2cUPQHMfjKEfg/g6oy7Hm6SKFtA==",
+                    "requires": {
+                        "@babel/helper-string-parser": "^7.22.5",
+                        "@babel/helper-validator-identifier": "^7.22.15",
+                        "to-fast-properties": "^2.0.0"
+                    }
+                }
             }
         },
         "@babel/helper-module-imports": {
@@ -453,15 +492,40 @@
             }
         },
         "@babel/helper-module-transforms": {
-            "version": "7.22.9",
-            "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.22.9.tgz",
-            "integrity": "sha512-t+WA2Xn5K+rTeGtC8jCsdAH52bjggG5TKRuRrAGNM/mjIbO4GxvlLMFOEz9wXY5I2XQ60PMFsAG2WIcG82dQMQ==",
+            "version": "7.22.15",
+            "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.22.15.tgz",
+            "integrity": "sha512-l1UiX4UyHSFsYt17iQ3Se5pQQZZHa22zyIXURmvkmLCD4t/aU+dvNWHatKac/D9Vm9UES7nvIqHs4jZqKviUmQ==",
             "requires": {
                 "@babel/helper-environment-visitor": "^7.22.5",
-                "@babel/helper-module-imports": "^7.22.5",
+                "@babel/helper-module-imports": "^7.22.15",
                 "@babel/helper-simple-access": "^7.22.5",
                 "@babel/helper-split-export-declaration": "^7.22.6",
-                "@babel/helper-validator-identifier": "^7.22.5"
+                "@babel/helper-validator-identifier": "^7.22.15"
+            },
+            "dependencies": {
+                "@babel/helper-module-imports": {
+                    "version": "7.22.15",
+                    "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz",
+                    "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==",
+                    "requires": {
+                        "@babel/types": "^7.22.15"
+                    }
+                },
+                "@babel/helper-validator-identifier": {
+                    "version": "7.22.15",
+                    "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.15.tgz",
+                    "integrity": "sha512-4E/F9IIEi8WR94324mbDUMo074YTheJmd7eZF5vITTeYchqAi6sYXRLHUVsmkdmY4QjfKTcB2jB7dVP3NaBElQ=="
+                },
+                "@babel/types": {
+                    "version": "7.22.15",
+                    "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.15.tgz",
+                    "integrity": "sha512-X+NLXr0N8XXmN5ZsaQdm9U2SSC3UbIYq/doL++sueHOTisgZHoKaQtZxGuV2cUPQHMfjKEfg/g6oy7Hm6SKFtA==",
+                    "requires": {
+                        "@babel/helper-string-parser": "^7.22.5",
+                        "@babel/helper-validator-identifier": "^7.22.15",
+                        "to-fast-properties": "^2.0.0"
+                    }
+                }
             }
         },
         "@babel/helper-optimise-call-expression": {
@@ -542,9 +606,9 @@
             "integrity": "sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ=="
         },
         "@babel/helper-validator-option": {
-            "version": "7.22.5",
-            "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.5.tgz",
-            "integrity": "sha512-R3oB6xlIVKUnxNUxbmgq7pKjxpru24zlimpE8WK47fACIlM0II/Hm1RS8IaOI7NgCr6LNS+jl5l75m20npAziw=="
+            "version": "7.22.15",
+            "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.15.tgz",
+            "integrity": "sha512-bMn7RmyFjY/mdECUbgn9eoSY4vqvacUnS9i9vGAGttgFWesO6B4CYWA7XlpbWgBt71iv/hfbPlynohStqnu5hA=="
         },
         "@babel/helper-wrap-function": {
             "version": "7.22.10",
@@ -556,26 +620,31 @@
                 "@babel/types": "^7.22.10"
             },
             "dependencies": {
+                "@babel/helper-validator-identifier": {
+                    "version": "7.22.15",
+                    "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.15.tgz",
+                    "integrity": "sha512-4E/F9IIEi8WR94324mbDUMo074YTheJmd7eZF5vITTeYchqAi6sYXRLHUVsmkdmY4QjfKTcB2jB7dVP3NaBElQ=="
+                },
                 "@babel/types": {
-                    "version": "7.22.11",
-                    "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.11.tgz",
-                    "integrity": "sha512-siazHiGuZRz9aB9NpHy9GOs9xiQPKnMzgdr493iI1M67vRXpnEq8ZOOKzezC5q7zwuQ6sDhdSp4SD9ixKSqKZg==",
+                    "version": "7.22.15",
+                    "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.15.tgz",
+                    "integrity": "sha512-X+NLXr0N8XXmN5ZsaQdm9U2SSC3UbIYq/doL++sueHOTisgZHoKaQtZxGuV2cUPQHMfjKEfg/g6oy7Hm6SKFtA==",
                     "requires": {
                         "@babel/helper-string-parser": "^7.22.5",
-                        "@babel/helper-validator-identifier": "^7.22.5",
+                        "@babel/helper-validator-identifier": "^7.22.15",
                         "to-fast-properties": "^2.0.0"
                     }
                 }
             }
         },
         "@babel/helpers": {
-            "version": "7.22.11",
-            "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.22.11.tgz",
-            "integrity": "sha512-vyOXC8PBWaGc5h7GMsNx68OH33cypkEDJCHvYVVgVbbxJDROYVtexSk0gK5iCF1xNjRIN2s8ai7hwkWDq5szWg==",
+            "version": "7.22.15",
+            "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.22.15.tgz",
+            "integrity": "sha512-7pAjK0aSdxOwR+CcYAqgWOGy5dcfvzsTIfFTb2odQqW47MDfv14UaJDY6eng8ylM2EaeKXdxaSWESbkmaQHTmw==",
             "requires": {
-                "@babel/template": "^7.22.5",
-                "@babel/traverse": "^7.22.11",
-                "@babel/types": "^7.22.11"
+                "@babel/template": "^7.22.15",
+                "@babel/traverse": "^7.22.15",
+                "@babel/types": "^7.22.15"
             },
             "dependencies": {
                 "@babel/code-frame": {
@@ -588,11 +657,11 @@
                     }
                 },
                 "@babel/generator": {
-                    "version": "7.22.10",
-                    "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.10.tgz",
-                    "integrity": "sha512-79KIf7YiWjjdZ81JnLujDRApWtl7BxTqWD88+FFdQEIOG8LJ0etDOM7CXuIgGJa55sGOwZVwuEsaLEm0PJ5/+A==",
+                    "version": "7.22.15",
+                    "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.15.tgz",
+                    "integrity": "sha512-Zu9oWARBqeVOW0dZOjXc3JObrzuqothQ3y/n1kUtrjCoCPLkXUwMvOo/F/TCfoHMbWIFlWwpZtkZVb9ga4U2pA==",
                     "requires": {
-                        "@babel/types": "^7.22.10",
+                        "@babel/types": "^7.22.15",
                         "@jridgewell/gen-mapping": "^0.3.2",
                         "@jridgewell/trace-mapping": "^0.3.17",
                         "jsesc": "^2.5.1"
@@ -609,35 +678,52 @@
                     }
                 },
                 "@babel/parser": {
-                    "version": "7.22.14",
-                    "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.14.tgz",
-                    "integrity": "sha512-1KucTHgOvaw/LzCVrEOAyXkr9rQlp0A1HiHRYnSUE9dmb8PvPW7o5sscg+5169r54n3vGlbx6GevTE/Iw/P3AQ=="
+                    "version": "7.22.16",
+                    "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.16.tgz",
+                    "integrity": "sha512-+gPfKv8UWeKKeJTUxe59+OobVcrYHETCsORl61EmSkmgymguYk/X5bp7GuUIXaFsc6y++v8ZxPsLSSuujqDphA=="
+                },
+                "@babel/template": {
+                    "version": "7.22.15",
+                    "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz",
+                    "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==",
+                    "requires": {
+                        "@babel/code-frame": "^7.22.13",
+                        "@babel/parser": "^7.22.15",
+                        "@babel/types": "^7.22.15"
+                    }
                 },
                 "@babel/traverse": {
-                    "version": "7.22.11",
-                    "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.11.tgz",
-                    "integrity": "sha512-mzAenteTfomcB7mfPtyi+4oe5BZ6MXxWcn4CX+h4IRJ+OOGXBrWU6jDQavkQI9Vuc5P+donFabBfFCcmWka9lQ==",
+                    "version": "7.22.15",
+                    "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.15.tgz",
+                    "integrity": "sha512-DdHPwvJY0sEeN4xJU5uRLmZjgMMDIvMPniLuYzUVXj/GGzysPl0/fwt44JBkyUIzGJPV8QgHMcQdQ34XFuKTYQ==",
                     "requires": {
-                        "@babel/code-frame": "^7.22.10",
-                        "@babel/generator": "^7.22.10",
+                        "@babel/code-frame": "^7.22.13",
+                        "@babel/generator": "^7.22.15",
                         "@babel/helper-environment-visitor": "^7.22.5",
                         "@babel/helper-function-name": "^7.22.5",
                         "@babel/helper-hoist-variables": "^7.22.5",
                         "@babel/helper-split-export-declaration": "^7.22.6",
-                        "@babel/parser": "^7.22.11",
-                        "@babel/types": "^7.22.11",
+                        "@babel/parser": "^7.22.15",
+                        "@babel/types": "^7.22.15",
                         "debug": "^4.1.0",
                         "globals": "^11.1.0"
                     }
                 },
                 "@babel/types": {
-                    "version": "7.22.11",
-                    "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.11.tgz",
-                    "integrity": "sha512-siazHiGuZRz9aB9NpHy9GOs9xiQPKnMzgdr493iI1M67vRXpnEq8ZOOKzezC5q7zwuQ6sDhdSp4SD9ixKSqKZg==",
+                    "version": "7.22.15",
+                    "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.15.tgz",
+                    "integrity": "sha512-X+NLXr0N8XXmN5ZsaQdm9U2SSC3UbIYq/doL++sueHOTisgZHoKaQtZxGuV2cUPQHMfjKEfg/g6oy7Hm6SKFtA==",
                     "requires": {
                         "@babel/helper-string-parser": "^7.22.5",
-                        "@babel/helper-validator-identifier": "^7.22.5",
+                        "@babel/helper-validator-identifier": "^7.22.15",
                         "to-fast-properties": "^2.0.0"
+                    },
+                    "dependencies": {
+                        "@babel/helper-validator-identifier": {
+                            "version": "7.22.15",
+                            "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.15.tgz",
+                            "integrity": "sha512-4E/F9IIEi8WR94324mbDUMo074YTheJmd7eZF5vITTeYchqAi6sYXRLHUVsmkdmY4QjfKTcB2jB7dVP3NaBElQ=="
+                        }
                     }
                 },
                 "debug": {
@@ -671,9 +757,9 @@
             "integrity": "sha512-7NF8pOkHP5o2vpmGgNGcfAeCvOYhGLyA3Z4eBQkT1RJlWu47n63bCs93QfJ2hIAFCil7L5P2IWhs1oToVgrL0Q=="
         },
         "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": {
-            "version": "7.22.5",
-            "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.22.5.tgz",
-            "integrity": "sha512-NP1M5Rf+u2Gw9qfSO4ihjcTGW5zXTi36ITLd4/EoAcEhIZ0yjMqmftDNl3QC19CX7olhrjpyU454g/2W7X0jvQ==",
+            "version": "7.22.15",
+            "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.22.15.tgz",
+            "integrity": "sha512-FB9iYlz7rURmRJyXRKEnalYPPdn87H5no108cyuQQyMwlpJ2SJtpIUBI27kdTin956pz+LPypkPVPUTlxOmrsg==",
             "requires": {
                 "@babel/helper-plugin-utils": "^7.22.5"
             },
@@ -686,13 +772,13 @@
             }
         },
         "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": {
-            "version": "7.22.5",
-            "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.22.5.tgz",
-            "integrity": "sha512-31Bb65aZaUwqCbWMnZPduIZxCBngHFlzyN6Dq6KAJjtx+lx6ohKHubc61OomYi7XwVD4Ol0XCVz4h+pYFR048g==",
+            "version": "7.22.15",
+            "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.22.15.tgz",
+            "integrity": "sha512-Hyph9LseGvAeeXzikV88bczhsrLrIZqDPxO+sSmAunMPaGrBGhfMWzCPYTtiW9t+HzSE2wtV8e5cc5P6r1xMDQ==",
             "requires": {
                 "@babel/helper-plugin-utils": "^7.22.5",
                 "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5",
-                "@babel/plugin-transform-optional-chaining": "^7.22.5"
+                "@babel/plugin-transform-optional-chaining": "^7.22.15"
             },
             "dependencies": {
                 "@babel/helper-plugin-utils": {
@@ -941,9 +1027,9 @@
             }
         },
         "@babel/plugin-transform-async-generator-functions": {
-            "version": "7.22.11",
-            "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.22.11.tgz",
-            "integrity": "sha512-0pAlmeRJn6wU84zzZsEOx1JV1Jf8fqO9ok7wofIJwUnplYo247dcd24P+cMJht7ts9xkzdtB0EPHmOb7F+KzXw==",
+            "version": "7.22.15",
+            "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.22.15.tgz",
+            "integrity": "sha512-jBm1Es25Y+tVoTi5rfd5t1KLmL8ogLKpXszboWOTTtGFGz2RKnQe2yn7HbZ+kb/B8N0FVSGQo874NSlOU1T4+w==",
             "requires": {
                 "@babel/helper-environment-visitor": "^7.22.5",
                 "@babel/helper-plugin-utils": "^7.22.5",
@@ -991,9 +1077,9 @@
             }
         },
         "@babel/plugin-transform-block-scoping": {
-            "version": "7.22.10",
-            "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.22.10.tgz",
-            "integrity": "sha512-1+kVpGAOOI1Albt6Vse7c8pHzcZQdQKW+wJH+g8mCaszOdDVwRXa/slHPqIw+oJAJANTKDMuM2cBdV0Dg618Vg==",
+            "version": "7.22.15",
+            "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.22.15.tgz",
+            "integrity": "sha512-G1czpdJBZCtngoK1sJgloLiOHUnkb/bLZwqVZD8kXmq0ZnVfTTWUcs9OWtp0mBtYJ+4LQY1fllqBkOIPhXmFmw==",
             "requires": {
                 "@babel/helper-plugin-utils": "^7.22.5"
             },
@@ -1039,17 +1125,17 @@
             }
         },
         "@babel/plugin-transform-classes": {
-            "version": "7.22.6",
-            "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.22.6.tgz",
-            "integrity": "sha512-58EgM6nuPNG6Py4Z3zSuu0xWu2VfodiMi72Jt5Kj2FECmaYk1RrTXA45z6KBFsu9tRgwQDwIiY4FXTt+YsSFAQ==",
+            "version": "7.22.15",
+            "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.22.15.tgz",
+            "integrity": "sha512-VbbC3PGjBdE0wAWDdHM9G8Gm977pnYI0XpqMd6LrKISj8/DJXEsWqgRuTYaNE9Bv0JGhTZUzHDlMk18IpOuoqw==",
             "requires": {
                 "@babel/helper-annotate-as-pure": "^7.22.5",
-                "@babel/helper-compilation-targets": "^7.22.6",
+                "@babel/helper-compilation-targets": "^7.22.15",
                 "@babel/helper-environment-visitor": "^7.22.5",
                 "@babel/helper-function-name": "^7.22.5",
                 "@babel/helper-optimise-call-expression": "^7.22.5",
                 "@babel/helper-plugin-utils": "^7.22.5",
-                "@babel/helper-replace-supers": "^7.22.5",
+                "@babel/helper-replace-supers": "^7.22.9",
                 "@babel/helper-split-export-declaration": "^7.22.6",
                 "globals": "^11.1.0"
             },
@@ -1086,9 +1172,9 @@
             }
         },
         "@babel/plugin-transform-destructuring": {
-            "version": "7.22.10",
-            "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.22.10.tgz",
-            "integrity": "sha512-dPJrL0VOyxqLM9sritNbMSGx/teueHF/htMKrPT7DNxccXxRDPYqlgPFFdr8u+F+qUZOkZoXue/6rL5O5GduEw==",
+            "version": "7.22.15",
+            "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.22.15.tgz",
+            "integrity": "sha512-HzG8sFl1ZVGTme74Nw+X01XsUTqERVQ6/RLHo3XjGRzm7XD6QTtfS3NJotVgCGy8BzkDqRjRBD8dAyJn5TuvSQ==",
             "requires": {
                 "@babel/helper-plugin-utils": "^7.22.5"
             },
@@ -1180,9 +1266,9 @@
             }
         },
         "@babel/plugin-transform-for-of": {
-            "version": "7.22.5",
-            "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.22.5.tgz",
-            "integrity": "sha512-3kxQjX1dU9uudwSshyLeEipvrLjBCVthCgeTp6CzE/9JYrlAIaeekVxRpCWsDDfYTfRZRoCeZatCQvwo+wvK8A==",
+            "version": "7.22.15",
+            "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.22.15.tgz",
+            "integrity": "sha512-me6VGeHsx30+xh9fbDLLPi0J1HzmeIIyenoOQHuw2D4m2SAU3NrspX5XxJLBpqn5yrLzrlw2Iy3RA//Bx27iOA==",
             "requires": {
                 "@babel/helper-plugin-utils": "^7.22.5"
             },
@@ -1290,11 +1376,11 @@
             }
         },
         "@babel/plugin-transform-modules-commonjs": {
-            "version": "7.22.11",
-            "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.22.11.tgz",
-            "integrity": "sha512-o2+bg7GDS60cJMgz9jWqRUsWkMzLCxp+jFDeDUT5sjRlAxcJWZ2ylNdI7QQ2+CH5hWu7OnN+Cv3htt7AkSf96g==",
+            "version": "7.22.15",
+            "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.22.15.tgz",
+            "integrity": "sha512-jWL4eh90w0HQOTKP2MoXXUpVxilxsB2Vl4ji69rSjS3EcZ/v4sBmn+A3NpepuJzBhOaEBbR7udonlHHn5DWidg==",
             "requires": {
-                "@babel/helper-module-transforms": "^7.22.9",
+                "@babel/helper-module-transforms": "^7.22.15",
                 "@babel/helper-plugin-utils": "^7.22.5",
                 "@babel/helper-simple-access": "^7.22.5"
             },
@@ -1404,15 +1490,15 @@
             }
         },
         "@babel/plugin-transform-object-rest-spread": {
-            "version": "7.22.11",
-            "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.22.11.tgz",
-            "integrity": "sha512-nX8cPFa6+UmbepISvlf5jhQyaC7ASs/7UxHmMkuJ/k5xSHvDPPaibMo+v3TXwU/Pjqhep/nFNpd3zn4YR59pnw==",
+            "version": "7.22.15",
+            "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.22.15.tgz",
+            "integrity": "sha512-fEB+I1+gAmfAyxZcX1+ZUwLeAuuf8VIg67CTznZE0MqVFumWkh8xWtn58I4dxdVf080wn7gzWoF8vndOViJe9Q==",
             "requires": {
                 "@babel/compat-data": "^7.22.9",
-                "@babel/helper-compilation-targets": "^7.22.10",
+                "@babel/helper-compilation-targets": "^7.22.15",
                 "@babel/helper-plugin-utils": "^7.22.5",
                 "@babel/plugin-syntax-object-rest-spread": "^7.8.3",
-                "@babel/plugin-transform-parameters": "^7.22.5"
+                "@babel/plugin-transform-parameters": "^7.22.15"
             },
             "dependencies": {
                 "@babel/helper-plugin-utils": {
@@ -1455,9 +1541,9 @@
             }
         },
         "@babel/plugin-transform-optional-chaining": {
-            "version": "7.22.12",
-            "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.22.12.tgz",
-            "integrity": "sha512-7XXCVqZtyFWqjDsYDY4T45w4mlx1rf7aOgkc/Ww76xkgBiOlmjPkx36PBLHa1k1rwWvVgYMPsbuVnIamx2ZQJw==",
+            "version": "7.22.15",
+            "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.22.15.tgz",
+            "integrity": "sha512-ngQ2tBhq5vvSJw2Q2Z9i7ealNkpDMU0rGWnHPKqRZO0tzZ5tlaoz4hDvhXioOoaE0X2vfNss1djwg0DXlfu30A==",
             "requires": {
                 "@babel/helper-plugin-utils": "^7.22.5",
                 "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5",
@@ -1472,9 +1558,9 @@
             }
         },
         "@babel/plugin-transform-parameters": {
-            "version": "7.22.5",
-            "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.22.5.tgz",
-            "integrity": "sha512-AVkFUBurORBREOmHRKo06FjHYgjrabpdqRSwq6+C7R5iTCZOsM4QbcB27St0a4U6fffyAOqh3s/qEfybAhfivg==",
+            "version": "7.22.15",
+            "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.22.15.tgz",
+            "integrity": "sha512-hjk7qKIqhyzhhUvRT683TYQOFa/4cQKwQy7ALvTpODswN40MljzNDa0YldevS6tGbxwaEKVn502JmY0dP7qEtQ==",
             "requires": {
                 "@babel/helper-plugin-utils": "^7.22.5"
             },
@@ -1559,15 +1645,15 @@
             }
         },
         "@babel/plugin-transform-react-jsx": {
-            "version": "7.22.5",
-            "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.22.5.tgz",
-            "integrity": "sha512-rog5gZaVbUip5iWDMTYbVM15XQq+RkUKhET/IHR6oizR+JEoN6CAfTTuHcK4vwUyzca30qqHqEpzBOnaRMWYMA==",
+            "version": "7.22.15",
+            "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.22.15.tgz",
+            "integrity": "sha512-oKckg2eZFa8771O/5vi7XeTvmM6+O9cxZu+kanTU7tD4sin5nO/G8jGJhq8Hvt2Z0kUoEDRayuZLaUlYl8QuGA==",
             "requires": {
                 "@babel/helper-annotate-as-pure": "^7.22.5",
-                "@babel/helper-module-imports": "^7.22.5",
+                "@babel/helper-module-imports": "^7.22.15",
                 "@babel/helper-plugin-utils": "^7.22.5",
                 "@babel/plugin-syntax-jsx": "^7.22.5",
-                "@babel/types": "^7.22.5"
+                "@babel/types": "^7.22.15"
             },
             "dependencies": {
                 "@babel/helper-annotate-as-pure": {
@@ -1578,11 +1664,24 @@
                         "@babel/types": "^7.22.5"
                     }
                 },
+                "@babel/helper-module-imports": {
+                    "version": "7.22.15",
+                    "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz",
+                    "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==",
+                    "requires": {
+                        "@babel/types": "^7.22.15"
+                    }
+                },
                 "@babel/helper-plugin-utils": {
                     "version": "7.22.5",
                     "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
                     "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
                 },
+                "@babel/helper-validator-identifier": {
+                    "version": "7.22.15",
+                    "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.15.tgz",
+                    "integrity": "sha512-4E/F9IIEi8WR94324mbDUMo074YTheJmd7eZF5vITTeYchqAi6sYXRLHUVsmkdmY4QjfKTcB2jB7dVP3NaBElQ=="
+                },
                 "@babel/plugin-syntax-jsx": {
                     "version": "7.22.5",
                     "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.22.5.tgz",
@@ -1590,6 +1689,16 @@
                     "requires": {
                         "@babel/helper-plugin-utils": "^7.22.5"
                     }
+                },
+                "@babel/types": {
+                    "version": "7.22.15",
+                    "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.15.tgz",
+                    "integrity": "sha512-X+NLXr0N8XXmN5ZsaQdm9U2SSC3UbIYq/doL++sueHOTisgZHoKaQtZxGuV2cUPQHMfjKEfg/g6oy7Hm6SKFtA==",
+                    "requires": {
+                        "@babel/helper-string-parser": "^7.22.5",
+                        "@babel/helper-validator-identifier": "^7.22.15",
+                        "to-fast-properties": "^2.0.0"
+                    }
                 }
             }
         },
@@ -1733,12 +1842,12 @@
             }
         },
         "@babel/plugin-transform-typescript": {
-            "version": "7.22.11",
-            "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.22.11.tgz",
-            "integrity": "sha512-0E4/L+7gfvHub7wsbTv03oRtD69X31LByy44fGmFzbZScpupFByMcgCJ0VbBTkzyjSJKuRoGN8tcijOWKTmqOA==",
+            "version": "7.22.15",
+            "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.22.15.tgz",
+            "integrity": "sha512-1uirS0TnijxvQLnlv5wQBwOX3E1wCFX7ITv+9pBV2wKEk4K+M5tqDaoNXnTH8tjEIYHLO98MwiTWO04Ggz4XuA==",
             "requires": {
                 "@babel/helper-annotate-as-pure": "^7.22.5",
-                "@babel/helper-create-class-features-plugin": "^7.22.11",
+                "@babel/helper-create-class-features-plugin": "^7.22.15",
                 "@babel/helper-plugin-utils": "^7.22.5",
                 "@babel/plugin-syntax-typescript": "^7.22.5"
             },
@@ -1822,16 +1931,16 @@
             }
         },
         "@babel/preset-env": {
-            "version": "7.22.14",
-            "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.22.14.tgz",
-            "integrity": "sha512-daodMIoVo+ol/g+//c/AH+szBkFj4STQUikvBijRGL72Ph+w+AMTSh55DUETe8KJlPlDT1k/mp7NBfOuiWmoig==",
+            "version": "7.22.15",
+            "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.22.15.tgz",
+            "integrity": "sha512-tZFHr54GBkHk6hQuVA8w4Fmq+MSPsfvMG0vPnOYyTnJpyfMqybL8/MbNCPRT9zc2KBO2pe4tq15g6Uno4Jpoag==",
             "requires": {
                 "@babel/compat-data": "^7.22.9",
-                "@babel/helper-compilation-targets": "^7.22.10",
+                "@babel/helper-compilation-targets": "^7.22.15",
                 "@babel/helper-plugin-utils": "^7.22.5",
-                "@babel/helper-validator-option": "^7.22.5",
-                "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.22.5",
-                "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.22.5",
+                "@babel/helper-validator-option": "^7.22.15",
+                "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.22.15",
+                "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.22.15",
                 "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2",
                 "@babel/plugin-syntax-async-generators": "^7.8.4",
                 "@babel/plugin-syntax-class-properties": "^7.12.13",
@@ -1852,39 +1961,39 @@
                 "@babel/plugin-syntax-top-level-await": "^7.14.5",
                 "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6",
                 "@babel/plugin-transform-arrow-functions": "^7.22.5",
-                "@babel/plugin-transform-async-generator-functions": "^7.22.11",
+                "@babel/plugin-transform-async-generator-functions": "^7.22.15",
                 "@babel/plugin-transform-async-to-generator": "^7.22.5",
                 "@babel/plugin-transform-block-scoped-functions": "^7.22.5",
-                "@babel/plugin-transform-block-scoping": "^7.22.10",
+                "@babel/plugin-transform-block-scoping": "^7.22.15",
                 "@babel/plugin-transform-class-properties": "^7.22.5",
                 "@babel/plugin-transform-class-static-block": "^7.22.11",
-                "@babel/plugin-transform-classes": "^7.22.6",
+                "@babel/plugin-transform-classes": "^7.22.15",
                 "@babel/plugin-transform-computed-properties": "^7.22.5",
-                "@babel/plugin-transform-destructuring": "^7.22.10",
+                "@babel/plugin-transform-destructuring": "^7.22.15",
                 "@babel/plugin-transform-dotall-regex": "^7.22.5",
                 "@babel/plugin-transform-duplicate-keys": "^7.22.5",
                 "@babel/plugin-transform-dynamic-import": "^7.22.11",
                 "@babel/plugin-transform-exponentiation-operator": "^7.22.5",
                 "@babel/plugin-transform-export-namespace-from": "^7.22.11",
-                "@babel/plugin-transform-for-of": "^7.22.5",
+                "@babel/plugin-transform-for-of": "^7.22.15",
                 "@babel/plugin-transform-function-name": "^7.22.5",
                 "@babel/plugin-transform-json-strings": "^7.22.11",
                 "@babel/plugin-transform-literals": "^7.22.5",
                 "@babel/plugin-transform-logical-assignment-operators": "^7.22.11",
                 "@babel/plugin-transform-member-expression-literals": "^7.22.5",
                 "@babel/plugin-transform-modules-amd": "^7.22.5",
-                "@babel/plugin-transform-modules-commonjs": "^7.22.11",
+                "@babel/plugin-transform-modules-commonjs": "^7.22.15",
                 "@babel/plugin-transform-modules-systemjs": "^7.22.11",
                 "@babel/plugin-transform-modules-umd": "^7.22.5",
                 "@babel/plugin-transform-named-capturing-groups-regex": "^7.22.5",
                 "@babel/plugin-transform-new-target": "^7.22.5",
                 "@babel/plugin-transform-nullish-coalescing-operator": "^7.22.11",
                 "@babel/plugin-transform-numeric-separator": "^7.22.11",
-                "@babel/plugin-transform-object-rest-spread": "^7.22.11",
+                "@babel/plugin-transform-object-rest-spread": "^7.22.15",
                 "@babel/plugin-transform-object-super": "^7.22.5",
                 "@babel/plugin-transform-optional-catch-binding": "^7.22.11",
-                "@babel/plugin-transform-optional-chaining": "^7.22.12",
-                "@babel/plugin-transform-parameters": "^7.22.5",
+                "@babel/plugin-transform-optional-chaining": "^7.22.15",
+                "@babel/plugin-transform-parameters": "^7.22.15",
                 "@babel/plugin-transform-private-methods": "^7.22.5",
                 "@babel/plugin-transform-private-property-in-object": "^7.22.11",
                 "@babel/plugin-transform-property-literals": "^7.22.5",
@@ -1900,7 +2009,7 @@
                 "@babel/plugin-transform-unicode-regex": "^7.22.5",
                 "@babel/plugin-transform-unicode-sets-regex": "^7.22.5",
                 "@babel/preset-modules": "0.1.6-no-external-plugins",
-                "@babel/types": "^7.22.11",
+                "@babel/types": "^7.22.15",
                 "babel-plugin-polyfill-corejs2": "^0.4.5",
                 "babel-plugin-polyfill-corejs3": "^0.8.3",
                 "babel-plugin-polyfill-regenerator": "^0.5.2",
@@ -1913,13 +2022,18 @@
                     "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
                     "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg=="
                 },
+                "@babel/helper-validator-identifier": {
+                    "version": "7.22.15",
+                    "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.15.tgz",
+                    "integrity": "sha512-4E/F9IIEi8WR94324mbDUMo074YTheJmd7eZF5vITTeYchqAi6sYXRLHUVsmkdmY4QjfKTcB2jB7dVP3NaBElQ=="
+                },
                 "@babel/types": {
-                    "version": "7.22.11",
-                    "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.11.tgz",
-                    "integrity": "sha512-siazHiGuZRz9aB9NpHy9GOs9xiQPKnMzgdr493iI1M67vRXpnEq8ZOOKzezC5q7zwuQ6sDhdSp4SD9ixKSqKZg==",
+                    "version": "7.22.15",
+                    "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.15.tgz",
+                    "integrity": "sha512-X+NLXr0N8XXmN5ZsaQdm9U2SSC3UbIYq/doL++sueHOTisgZHoKaQtZxGuV2cUPQHMfjKEfg/g6oy7Hm6SKFtA==",
                     "requires": {
                         "@babel/helper-string-parser": "^7.22.5",
-                        "@babel/helper-validator-identifier": "^7.22.5",
+                        "@babel/helper-validator-identifier": "^7.22.15",
                         "to-fast-properties": "^2.0.0"
                     }
                 },
@@ -1941,14 +2055,14 @@
             }
         },
         "@babel/preset-react": {
-            "version": "7.22.5",
-            "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.22.5.tgz",
-            "integrity": "sha512-M+Is3WikOpEJHgR385HbuCITPTaPRaNkibTEa9oiofmJvIsrceb4yp9RL9Kb+TE8LznmeyZqpP+Lopwcx59xPQ==",
+            "version": "7.22.15",
+            "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.22.15.tgz",
+            "integrity": "sha512-Csy1IJ2uEh/PecCBXXoZGAZBeCATTuePzCSB7dLYWS0vOEj6CNpjxIhW4duWwZodBNueH7QO14WbGn8YyeuN9w==",
             "requires": {
                 "@babel/helper-plugin-utils": "^7.22.5",
-                "@babel/helper-validator-option": "^7.22.5",
+                "@babel/helper-validator-option": "^7.22.15",
                 "@babel/plugin-transform-react-display-name": "^7.22.5",
-                "@babel/plugin-transform-react-jsx": "^7.22.5",
+                "@babel/plugin-transform-react-jsx": "^7.22.15",
                 "@babel/plugin-transform-react-jsx-development": "^7.22.5",
                 "@babel/plugin-transform-react-pure-annotations": "^7.22.5"
             },
@@ -1961,15 +2075,15 @@
             }
         },
         "@babel/preset-typescript": {
-            "version": "7.22.11",
-            "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.22.11.tgz",
-            "integrity": "sha512-tWY5wyCZYBGY7IlalfKI1rLiGlIfnwsRHZqlky0HVv8qviwQ1Uo/05M6+s+TcTCVa6Bmoo2uJW5TMFX6Wa4qVg==",
+            "version": "7.22.15",
+            "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.22.15.tgz",
+            "integrity": "sha512-HblhNmh6yM+cU4VwbBRpxFhxsTdfS1zsvH9W+gEjD0ARV9+8B4sNfpI6GuhePti84nuvhiwKS539jKPFHskA9A==",
             "requires": {
                 "@babel/helper-plugin-utils": "^7.22.5",
-                "@babel/helper-validator-option": "^7.22.5",
+                "@babel/helper-validator-option": "^7.22.15",
                 "@babel/plugin-syntax-jsx": "^7.22.5",
-                "@babel/plugin-transform-modules-commonjs": "^7.22.11",
-                "@babel/plugin-transform-typescript": "^7.22.11"
+                "@babel/plugin-transform-modules-commonjs": "^7.22.15",
+                "@babel/plugin-transform-typescript": "^7.22.15"
             },
             "dependencies": {
                 "@babel/helper-plugin-utils": {
@@ -3232,18 +3346,18 @@
             }
         },
         "@mui/styled-engine-sc": {
-            "version": "5.14.7",
-            "resolved": "https://registry.npmjs.org/@mui/styled-engine-sc/-/styled-engine-sc-5.14.7.tgz",
-            "integrity": "sha512-so3X2N0SxpXjc61+d6s0aG11OVF9XTDrKusaXd8YE1d9fzEuIGEpvOXizaMJZThqkTqGzNKQuXFEpC55Vb0gdw==",
+            "version": "5.14.8",
+            "resolved": "https://registry.npmjs.org/@mui/styled-engine-sc/-/styled-engine-sc-5.14.8.tgz",
+            "integrity": "sha512-s4bu3oqE2s3eeB6v/03NRB0N0yswA74Azn6N53PPq87dsvGOyvKLj707bJe+9HfbcbkdksQXP+2NUDmtmUDcig==",
             "requires": {
                 "@babel/runtime": "^7.22.10",
                 "prop-types": "^15.8.1"
             },
             "dependencies": {
                 "@babel/runtime": {
-                    "version": "7.22.11",
-                    "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.11.tgz",
-                    "integrity": "sha512-ee7jVNlWN09+KftVOu9n7S8gQzD/Z6hN/I8VBRXW4P1+Xe7kJGXMwu8vds4aGIMHZnNbdpSWCfZZtinytpcAvA==",
+                    "version": "7.22.15",
+                    "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.15.tgz",
+                    "integrity": "sha512-T0O+aa+4w0u06iNmapipJXMV4HoUir03hpx3/YqXXhu9xim3w+dVphjFWl1OH8NbZHw5Lbm9k45drDkgq2VNNA==",
                     "requires": {
                         "regenerator-runtime": "^0.14.0"
                     }
@@ -6537,9 +6651,9 @@
             }
         },
         "browndash-components": {
-            "version": "0.1.21",
-            "resolved": "https://registry.npmjs.org/browndash-components/-/browndash-components-0.1.21.tgz",
-            "integrity": "sha512-xPHuliete1jNXCGYZrVxuKUDmlanleFLWjZm8dC3vII0BT7jNPxMRZyYTxgc/PjYMRgM/BY0FCUPFTrsiYRawQ==",
+            "version": "0.1.22",
+            "resolved": "https://registry.npmjs.org/browndash-components/-/browndash-components-0.1.22.tgz",
+            "integrity": "sha512-xA1gRMdwVyKOXPyRGd5p1jXke9JvvRJJB4RFA+eIM79vJuzC5I3PVuXVhOpEpr7ZKFJay6qkP1Q5tGlYq570tg==",
             "requires": {
                 "@emotion/react": "^11.11.1",
                 "@emotion/styled": "^11.11.0",
@@ -6554,9 +6668,9 @@
             },
             "dependencies": {
                 "@babel/cli": {
-                    "version": "7.22.10",
-                    "resolved": "https://registry.npmjs.org/@babel/cli/-/cli-7.22.10.tgz",
-                    "integrity": "sha512-rM9ZMmaII630zGvtMtQ3P4GyHs28CHLYE9apLG7L8TgaSqcfoIGrlLSLsh4Q8kDTdZQQEXZm1M0nQtOvU/2heg==",
+                    "version": "7.22.15",
+                    "resolved": "https://registry.npmjs.org/@babel/cli/-/cli-7.22.15.tgz",
+                    "integrity": "sha512-prtg5f6zCERIaECeTZzd2fMtVjlfjhUcO+fBLQ6DXXdq5FljN+excVitJ2nogsusdf31LeqkjAfXZ7Xq+HmN8g==",
                     "requires": {
                         "@jridgewell/trace-mapping": "^0.3.17",
                         "@nicolo-ribaudo/chokidar-2": "2.1.8-no-fsevents.3",
@@ -6657,15 +6771,15 @@
                     "integrity": "sha512-EsBwpc7hBUJWAsNPBmJy4hxWx12v6bshQsldrVmjxJoc3isbxhOrF2IcCpaXxfvq03NwkI7sbsOLXbYuqF/8Ww=="
                 },
                 "@mui/base": {
-                    "version": "5.0.0-beta.13",
-                    "resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-beta.13.tgz",
-                    "integrity": "sha512-uC0l97pBspfDAp+iz2cJq8YZ8Sd9i73V77+WzUiOAckIVEyCm5dyVDZCCO2/phmzckVEeZCGcytybkjMQuhPQw==",
+                    "version": "5.0.0-beta.14",
+                    "resolved": "https://registry.npmjs.org/@mui/base/-/base-5.0.0-beta.14.tgz",
+                    "integrity": "sha512-Je/9JzzYObsuLCIClgE8XvXNFb55IEz8n2NtStUfASfNiVrwiR8t6VVFFuhofehkyTIN34tq1qbBaOjCnOovBw==",
                     "requires": {
                         "@babel/runtime": "^7.22.10",
                         "@emotion/is-prop-valid": "^1.2.1",
                         "@floating-ui/react-dom": "^2.0.1",
                         "@mui/types": "^7.2.4",
-                        "@mui/utils": "^5.14.7",
+                        "@mui/utils": "^5.14.8",
                         "@popperjs/core": "^2.11.8",
                         "clsx": "^2.0.0",
                         "prop-types": "^15.8.1",
@@ -6673,9 +6787,9 @@
                     },
                     "dependencies": {
                         "@babel/runtime": {
-                            "version": "7.22.11",
-                            "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.11.tgz",
-                            "integrity": "sha512-ee7jVNlWN09+KftVOu9n7S8gQzD/Z6hN/I8VBRXW4P1+Xe7kJGXMwu8vds4aGIMHZnNbdpSWCfZZtinytpcAvA==",
+                            "version": "7.22.15",
+                            "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.15.tgz",
+                            "integrity": "sha512-T0O+aa+4w0u06iNmapipJXMV4HoUir03hpx3/YqXXhu9xim3w+dVphjFWl1OH8NbZHw5Lbm9k45drDkgq2VNNA==",
                             "requires": {
                                 "regenerator-runtime": "^0.14.0"
                             }
@@ -6683,21 +6797,21 @@
                     }
                 },
                 "@mui/core-downloads-tracker": {
-                    "version": "5.14.7",
-                    "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.14.7.tgz",
-                    "integrity": "sha512-sCWTUNElBPgB30iLvWe3PU7SIlTKZNf6/E/sko85iHVeHCM6WPkDw+y89CrZYjhFNmPqt2fIQM/pZu+rP2lFLA=="
+                    "version": "5.14.8",
+                    "resolved": "https://registry.npmjs.org/@mui/core-downloads-tracker/-/core-downloads-tracker-5.14.8.tgz",
+                    "integrity": "sha512-8V7ZOC/lKkM03TRHqaThQFIq6bWPnj7L/ZWPh0ymldYFFyh8XdF0ywTgafsofDNYT4StlNknbaTjVHBma3SNjQ=="
                 },
                 "@mui/material": {
-                    "version": "5.14.7",
-                    "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.14.7.tgz",
-                    "integrity": "sha512-jIZj9F7zMv6IlyaYDVv5M2Kp20jIX8c0kzuwteySHS/A0IvPVyomQEPtWc51MCbpDNCqzwoZUp3rQtA2lI8k7A==",
+                    "version": "5.14.8",
+                    "resolved": "https://registry.npmjs.org/@mui/material/-/material-5.14.8.tgz",
+                    "integrity": "sha512-fqvDGGF1pXwOOL/f0Gw+KHo/67hasRpf2ApTIJkbuONOk9AUb2jnYMEqCWmL2sUcbbE3ShMbHl8N7HPSsRv1/A==",
                     "requires": {
                         "@babel/runtime": "^7.22.10",
-                        "@mui/base": "5.0.0-beta.13",
-                        "@mui/core-downloads-tracker": "^5.14.7",
-                        "@mui/system": "^5.14.7",
+                        "@mui/base": "5.0.0-beta.14",
+                        "@mui/core-downloads-tracker": "^5.14.8",
+                        "@mui/system": "^5.14.8",
                         "@mui/types": "^7.2.4",
-                        "@mui/utils": "^5.14.7",
+                        "@mui/utils": "^5.14.8",
                         "@types/react-transition-group": "^4.4.6",
                         "clsx": "^2.0.0",
                         "csstype": "^3.1.2",
@@ -6707,9 +6821,9 @@
                     },
                     "dependencies": {
                         "@babel/runtime": {
-                            "version": "7.22.11",
-                            "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.11.tgz",
-                            "integrity": "sha512-ee7jVNlWN09+KftVOu9n7S8gQzD/Z6hN/I8VBRXW4P1+Xe7kJGXMwu8vds4aGIMHZnNbdpSWCfZZtinytpcAvA==",
+                            "version": "7.22.15",
+                            "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.15.tgz",
+                            "integrity": "sha512-T0O+aa+4w0u06iNmapipJXMV4HoUir03hpx3/YqXXhu9xim3w+dVphjFWl1OH8NbZHw5Lbm9k45drDkgq2VNNA==",
                             "requires": {
                                 "regenerator-runtime": "^0.14.0"
                             }
@@ -6717,19 +6831,19 @@
                     }
                 },
                 "@mui/private-theming": {
-                    "version": "5.14.7",
-                    "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.14.7.tgz",
-                    "integrity": "sha512-Y86+hmDnJab2Ka42PgxKpK3oL7EiacbeeX3X/lG9LGO0wSc45wZjHeTfIlVSkkUCkexiMKEJp5NlSjZhr27NRQ==",
+                    "version": "5.14.8",
+                    "resolved": "https://registry.npmjs.org/@mui/private-theming/-/private-theming-5.14.8.tgz",
+                    "integrity": "sha512-iBzpcl3Mh92XaYpYPdgzzRxNGkjpoDz8rf8/q5m+EBPowFEHV+CCS9hC0Q2pOKLW3VFFikA7w/GHt7n++40JGQ==",
                     "requires": {
                         "@babel/runtime": "^7.22.10",
-                        "@mui/utils": "^5.14.7",
+                        "@mui/utils": "^5.14.8",
                         "prop-types": "^15.8.1"
                     },
                     "dependencies": {
                         "@babel/runtime": {
-                            "version": "7.22.11",
-                            "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.11.tgz",
-                            "integrity": "sha512-ee7jVNlWN09+KftVOu9n7S8gQzD/Z6hN/I8VBRXW4P1+Xe7kJGXMwu8vds4aGIMHZnNbdpSWCfZZtinytpcAvA==",
+                            "version": "7.22.15",
+                            "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.15.tgz",
+                            "integrity": "sha512-T0O+aa+4w0u06iNmapipJXMV4HoUir03hpx3/YqXXhu9xim3w+dVphjFWl1OH8NbZHw5Lbm9k45drDkgq2VNNA==",
                             "requires": {
                                 "regenerator-runtime": "^0.14.0"
                             }
@@ -6737,9 +6851,9 @@
                     }
                 },
                 "@mui/styled-engine": {
-                    "version": "5.14.7",
-                    "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-5.14.7.tgz",
-                    "integrity": "sha512-hKBETEDsIAkL8/mBwPiQj/vw28OeIhMXC3Tvj4J2bb9snxAKpiZioR1PwqP+6P41twsC/GKBd0Vr9oaWYaHuMg==",
+                    "version": "5.14.8",
+                    "resolved": "https://registry.npmjs.org/@mui/styled-engine/-/styled-engine-5.14.8.tgz",
+                    "integrity": "sha512-LGwOav/Y40PZWZ2yDk4beUoRlc57Vg+Vpxi9V9BBtT2ESAucCgFobkt+T8eVLMWF9huUou5pwKgLSU5pF90hBg==",
                     "requires": {
                         "@babel/runtime": "^7.22.10",
                         "@emotion/cache": "^11.11.0",
@@ -6748,9 +6862,9 @@
                     },
                     "dependencies": {
                         "@babel/runtime": {
-                            "version": "7.22.11",
-                            "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.11.tgz",
-                            "integrity": "sha512-ee7jVNlWN09+KftVOu9n7S8gQzD/Z6hN/I8VBRXW4P1+Xe7kJGXMwu8vds4aGIMHZnNbdpSWCfZZtinytpcAvA==",
+                            "version": "7.22.15",
+                            "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.15.tgz",
+                            "integrity": "sha512-T0O+aa+4w0u06iNmapipJXMV4HoUir03hpx3/YqXXhu9xim3w+dVphjFWl1OH8NbZHw5Lbm9k45drDkgq2VNNA==",
                             "requires": {
                                 "regenerator-runtime": "^0.14.0"
                             }
@@ -6758,24 +6872,24 @@
                     }
                 },
                 "@mui/system": {
-                    "version": "5.14.7",
-                    "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.14.7.tgz",
-                    "integrity": "sha512-jeZtHglc+Pi6qjGoopT6O4RqYXVBMqHVOsjMGP0hxGSSPm1T4gsAu7jU8eqGx9YwwjvvJ0eotTjFqw7iJ6qE2Q==",
+                    "version": "5.14.8",
+                    "resolved": "https://registry.npmjs.org/@mui/system/-/system-5.14.8.tgz",
+                    "integrity": "sha512-Dxnasv7Pj5hYe4ZZFKJZu4ufKm6cxpitWt3A+qMPps22YhqyeEqgDBq/HsAB3GOjqDP40fTAvQvS/Hguf4SJuw==",
                     "requires": {
                         "@babel/runtime": "^7.22.10",
-                        "@mui/private-theming": "^5.14.7",
-                        "@mui/styled-engine": "^5.14.7",
+                        "@mui/private-theming": "^5.14.8",
+                        "@mui/styled-engine": "^5.14.8",
                         "@mui/types": "^7.2.4",
-                        "@mui/utils": "^5.14.7",
+                        "@mui/utils": "^5.14.8",
                         "clsx": "^2.0.0",
                         "csstype": "^3.1.2",
                         "prop-types": "^15.8.1"
                     },
                     "dependencies": {
                         "@babel/runtime": {
-                            "version": "7.22.11",
-                            "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.11.tgz",
-                            "integrity": "sha512-ee7jVNlWN09+KftVOu9n7S8gQzD/Z6hN/I8VBRXW4P1+Xe7kJGXMwu8vds4aGIMHZnNbdpSWCfZZtinytpcAvA==",
+                            "version": "7.22.15",
+                            "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.15.tgz",
+                            "integrity": "sha512-T0O+aa+4w0u06iNmapipJXMV4HoUir03hpx3/YqXXhu9xim3w+dVphjFWl1OH8NbZHw5Lbm9k45drDkgq2VNNA==",
                             "requires": {
                                 "regenerator-runtime": "^0.14.0"
                             }
@@ -6783,9 +6897,9 @@
                     }
                 },
                 "@mui/utils": {
-                    "version": "5.14.7",
-                    "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.14.7.tgz",
-                    "integrity": "sha512-RtheP/aBoPogVdi8vj8Vo2IFnRa4mZVmnD0RGlVZ49yF60rZs+xP4/KbpIrTr83xVs34QmHQ2aQ+IX7I0a0dDw==",
+                    "version": "5.14.8",
+                    "resolved": "https://registry.npmjs.org/@mui/utils/-/utils-5.14.8.tgz",
+                    "integrity": "sha512-1Ls2FfyY2yVSz9NEqedh3J8JAbbZAnUWkOWLE2f4/Hc4T5UWHMfzBLLrCqExfqyfyU+uXYJPGeNIsky6f8Gh5Q==",
                     "requires": {
                         "@babel/runtime": "^7.22.10",
                         "@types/prop-types": "^15.7.5",
@@ -6795,9 +6909,9 @@
                     },
                     "dependencies": {
                         "@babel/runtime": {
-                            "version": "7.22.11",
-                            "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.11.tgz",
-                            "integrity": "sha512-ee7jVNlWN09+KftVOu9n7S8gQzD/Z6hN/I8VBRXW4P1+Xe7kJGXMwu8vds4aGIMHZnNbdpSWCfZZtinytpcAvA==",
+                            "version": "7.22.15",
+                            "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.15.tgz",
+                            "integrity": "sha512-T0O+aa+4w0u06iNmapipJXMV4HoUir03hpx3/YqXXhu9xim3w+dVphjFWl1OH8NbZHw5Lbm9k45drDkgq2VNNA==",
                             "requires": {
                                 "regenerator-runtime": "^0.14.0"
                             }
@@ -7094,97 +7208,12 @@
                                         "strip-ansi": "^7.0.1"
                                     }
                                 },
-                                "string-width-cjs": {
-                                    "version": "npm:string-width@4.2.3",
-                                    "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
-                                    "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
-                                    "requires": {
-                                        "emoji-regex": "^8.0.0",
-                                        "is-fullwidth-code-point": "^3.0.0",
-                                        "strip-ansi": "^6.0.1"
-                                    },
-                                    "dependencies": {
-                                        "ansi-regex": {
-                                            "version": "5.0.1",
-                                            "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
-                                            "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="
-                                        },
-                                        "emoji-regex": {
-                                            "version": "8.0.0",
-                                            "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
-                                            "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
-                                        },
-                                        "strip-ansi": {
-                                            "version": "6.0.1",
-                                            "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
-                                            "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
-                                            "requires": {
-                                                "ansi-regex": "^5.0.1"
-                                            }
-                                        }
-                                    }
-                                },
                                 "strip-ansi": {
                                     "version": "7.1.0",
                                     "bundled": true,
                                     "requires": {
                                         "ansi-regex": "^6.0.1"
                                     }
-                                },
-                                "strip-ansi-cjs": {
-                                    "version": "npm:strip-ansi@6.0.1",
-                                    "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
-                                    "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
-                                    "requires": {
-                                        "ansi-regex": "^5.0.1"
-                                    },
-                                    "dependencies": {
-                                        "ansi-regex": {
-                                            "version": "5.0.1",
-                                            "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
-                                            "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="
-                                        }
-                                    }
-                                },
-                                "wrap-ansi-cjs": {
-                                    "version": "npm:wrap-ansi@7.0.0",
-                                    "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
-                                    "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
-                                    "requires": {
-                                        "ansi-styles": "^4.0.0",
-                                        "string-width": "^4.1.0",
-                                        "strip-ansi": "^6.0.0"
-                                    },
-                                    "dependencies": {
-                                        "ansi-regex": {
-                                            "version": "5.0.1",
-                                            "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
-                                            "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="
-                                        },
-                                        "emoji-regex": {
-                                            "version": "8.0.0",
-                                            "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
-                                            "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
-                                        },
-                                        "string-width": {
-                                            "version": "4.2.3",
-                                            "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
-                                            "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
-                                            "requires": {
-                                                "emoji-regex": "^8.0.0",
-                                                "is-fullwidth-code-point": "^3.0.0",
-                                                "strip-ansi": "^6.0.1"
-                                            }
-                                        },
-                                        "strip-ansi": {
-                                            "version": "6.0.1",
-                                            "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
-                                            "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
-                                            "requires": {
-                                                "ansi-regex": "^5.0.1"
-                                            }
-                                        }
-                                    }
                                 }
                             }
                         },
@@ -8689,7 +8718,7 @@
                             }
                         },
                         "string-width-cjs": {
-                            "version": "npm:string-width-cjs@4.2.3",
+                            "version": "npm:string-width@4.2.3",
                             "bundled": true,
                             "requires": {
                                 "emoji-regex": "^8.0.0",
@@ -8712,7 +8741,7 @@
                             }
                         },
                         "strip-ansi-cjs": {
-                            "version": "npm:strip-ansi-cjs@6.0.1",
+                            "version": "npm:strip-ansi@6.0.1",
                             "bundled": true,
                             "requires": {
                                 "ansi-regex": "^5.0.1"
@@ -8871,7 +8900,7 @@
                             }
                         },
                         "wrap-ansi-cjs": {
-                            "version": "npm:wrap-ansi-cjs@7.0.0",
+                            "version": "npm:wrap-ansi@7.0.0",
                             "bundled": true,
                             "requires": {
                                 "ansi-styles": "^4.0.0",
@@ -10062,9 +10091,9 @@
             "integrity": "sha512-GiZn9D4Z/rSYvTeg1ljAIsEqFm0LaN9gVtwDCrKL80zHtS31p9BAjmTxVqTQDMpwlMolJZOFntUG2uwyj7DAqw=="
         },
         "core-js-compat": {
-            "version": "3.32.1",
-            "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.32.1.tgz",
-            "integrity": "sha512-GSvKDv4wE0bPnQtjklV101juQ85g6H3rm5PDP20mqlS5j0kXF3pP97YvAu5hl+uFHqMictp3b2VxOHljWMAtuA==",
+            "version": "3.32.2",
+            "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.32.2.tgz",
+            "integrity": "sha512-+GjlguTDINOijtVRUxrQOv3kfu9rl+qPNdX2LTbJ/ZyVTuxK+ksVSAGX1nHstu4hrv1En/uPTtWgq2gI5wt4AQ==",
             "requires": {
                 "browserslist": "^4.21.10"
             },
@@ -10081,14 +10110,14 @@
                     }
                 },
                 "caniuse-lite": {
-                    "version": "1.0.30001525",
-                    "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001525.tgz",
-                    "integrity": "sha512-/3z+wB4icFt3r0USMwxujAqRvaD/B7rvGTsKhbhSQErVrJvkZCLhgNLJxU8MevahQVH6hCU9FsHdNUFbiwmE7Q=="
+                    "version": "1.0.30001528",
+                    "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001528.tgz",
+                    "integrity": "sha512-0Db4yyjR9QMNlsxh+kKWzQtkyflkG/snYheSzkjmvdEtEXB1+jt7A2HmSEiO6XIJPIbo92lHNGNySvE5pZcs5Q=="
                 },
                 "electron-to-chromium": {
-                    "version": "1.4.506",
-                    "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.506.tgz",
-                    "integrity": "sha512-xxGct4GPAKSRlrLBtJxJFYy74W11zX6PO9GyHgl/U+2s3Dp0ZEwAklDfNHXOWcvH7zWMpsmgbR0ggEuaYAVvHA=="
+                    "version": "1.4.510",
+                    "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.510.tgz",
+                    "integrity": "sha512-xPfLIPFcN/WLXBpQ/K4UgE98oUBO5Tia6BD4rkSR0wE7ep/PwBVlgvPJQrIBpmJGVAmUzwPKuDbVt9XV6+uC2g=="
                 }
             }
         },
diff --git a/package.json b/package.json
index 080132f2e..402074fa1 100644
--- a/package.json
+++ b/package.json
@@ -178,7 +178,7 @@
         "body-parser": "^1.19.2",
         "bootstrap": "^4.6.1",
         "brotli": "^1.3.3",
-        "browndash-components": "^0.1.21",
+        "browndash-components": "^0.1.22",
         "browser-assert": "^1.2.1",
         "bson": "^4.6.1",
         "canvas": "^2.9.3",
diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx
index e963e2f52..0044a2832 100644
--- a/src/client/views/collections/TabDocView.tsx
+++ b/src/client/views/collections/TabDocView.tsx
@@ -33,6 +33,7 @@ import { CollectionFreeFormView } from './collectionFreeForm/CollectionFreeFormV
 import { CollectionView } from './CollectionView';
 import './TabDocView.scss';
 import React = require('react');
+import { SettingsManager } from '../../util/SettingsManager';
 const _global = (window /* browser */ || global) /* node */ as any;
 
 interface TabDocViewProps {
@@ -567,60 +568,56 @@ export class TabMinimapView extends React.Component<TabMinimapViewProps> {
                 emptyFunction
             );
     };
-    render() {
-        if (!this.renderBounds) return null;
+    popup = () => {
+        if (!this.renderBounds) return <></>;
         const miniWidth = (this.props.PanelWidth() / NumCast(this.props.document._freeform_scale, 1) / this.renderBounds.dim) * 100;
         const miniHeight = (this.props.PanelHeight() / NumCast(this.props.document._freeform_scale, 1) / this.renderBounds.dim) * 100;
         const miniLeft = 50 + ((NumCast(this.props.document._freeform_panX) - this.renderBounds.cx) / this.renderBounds.dim) * 100 - miniWidth / 2;
         const miniTop = 50 + ((NumCast(this.props.document._freeform_panY) - this.renderBounds.cy) / this.renderBounds.dim) * 100 - miniHeight / 2;
         const miniSize = this.returnMiniSize();
         return (
-            <div className="miniMap-hidden">
-                <Popup
-                    icon={<FontAwesomeIcon icon="globe-asia" size="lg" />}
-                    color={StrCast(Doc.UserDoc().userVariantColor, Colors.MEDIUM_BLUE)}
-                    type={Type.TERT}
-                    onPointerDown={e => e.stopPropagation()}
-                    placement={'top-end'}
-                    popup={
-                        <div className="miniMap" style={{ width: miniSize, height: miniSize, background: this.props.background() }}>
-                            <CollectionFreeFormView
-                                Document={this.props.document}
-                                docViewPath={returnEmptyDoclist}
-                                childLayoutTemplate={this.childLayoutTemplate} // bcz: Ugh .. should probably be rendering a CollectionView or the minimap should be part of the collectionFreeFormView to avoid having to set stuff like this.
-                                noOverlay={true} // don't render overlay Docs since they won't scale
-                                setHeight={returnFalse}
-                                isContentActive={emptyFunction}
-                                isAnyChildContentActive={returnFalse}
-                                select={emptyFunction}
-                                isSelected={returnFalse}
-                                dontRegisterView={true}
-                                fieldKey={Doc.LayoutFieldKey(this.props.document)}
-                                bringToFront={emptyFunction}
-                                rootSelected={returnTrue}
-                                addDocument={returnFalse}
-                                moveDocument={returnFalse}
-                                removeDocument={returnFalse}
-                                PanelWidth={this.returnMiniSize}
-                                PanelHeight={this.returnMiniSize}
-                                ScreenToLocalTransform={Transform.Identity}
-                                renderDepth={0}
-                                whenChildContentsActiveChanged={emptyFunction}
-                                focus={emptyFunction}
-                                styleProvider={TabMinimapView.miniStyleProvider}
-                                addDocTab={this.props.addDocTab}
-                                pinToPres={TabDocView.PinDoc}
-                                childFilters={CollectionDockingView.Instance?.childDocFilters ?? returnEmptyDoclist}
-                                childFiltersByRanges={CollectionDockingView.Instance?.childDocRangeFilters ?? returnEmptyDoclist}
-                                searchFilterDocs={CollectionDockingView.Instance?.searchFilterDocs ?? returnEmptyDoclist}
-                                fitContentsToBox={returnTrue}
-                            />
-                            <div className="miniOverlay" onPointerDown={this.miniDown}>
-                                <div className="miniThumb" style={{ width: `${miniWidth}% `, height: `${miniHeight}% `, left: `${miniLeft}% `, top: `${miniTop}% ` }} />
-                            </div>
-                        </div>
-                    }
+            <div className="miniMap" style={{ width: miniSize, height: miniSize, background: this.props.background() }}>
+                <CollectionFreeFormView
+                    Document={this.props.document}
+                    docViewPath={returnEmptyDoclist}
+                    childLayoutTemplate={this.childLayoutTemplate} // bcz: Ugh .. should probably be rendering a CollectionView or the minimap should be part of the collectionFreeFormView to avoid having to set stuff like this.
+                    noOverlay={true} // don't render overlay Docs since they won't scale
+                    setHeight={returnFalse}
+                    isContentActive={emptyFunction}
+                    isAnyChildContentActive={returnFalse}
+                    select={emptyFunction}
+                    isSelected={returnFalse}
+                    dontRegisterView={true}
+                    fieldKey={Doc.LayoutFieldKey(this.props.document)}
+                    bringToFront={emptyFunction}
+                    rootSelected={returnTrue}
+                    addDocument={returnFalse}
+                    moveDocument={returnFalse}
+                    removeDocument={returnFalse}
+                    PanelWidth={this.returnMiniSize}
+                    PanelHeight={this.returnMiniSize}
+                    ScreenToLocalTransform={Transform.Identity}
+                    renderDepth={0}
+                    whenChildContentsActiveChanged={emptyFunction}
+                    focus={emptyFunction}
+                    styleProvider={TabMinimapView.miniStyleProvider}
+                    addDocTab={this.props.addDocTab}
+                    pinToPres={TabDocView.PinDoc}
+                    childFilters={CollectionDockingView.Instance?.childDocFilters ?? returnEmptyDoclist}
+                    childFiltersByRanges={CollectionDockingView.Instance?.childDocRangeFilters ?? returnEmptyDoclist}
+                    searchFilterDocs={CollectionDockingView.Instance?.searchFilterDocs ?? returnEmptyDoclist}
+                    fitContentsToBox={returnTrue}
                 />
+                <div className="miniOverlay" onPointerDown={this.miniDown}>
+                    <div className="miniThumb" style={{ width: `${miniWidth}% `, height: `${miniHeight}% `, left: `${miniLeft}% `, top: `${miniTop}% ` }} />
+                </div>
+            </div>
+        );
+    };
+    render() {
+        return (
+            <div className="miniMap-hidden">
+                <Popup icon={<FontAwesomeIcon icon="globe-asia" size="lg" />} color={SettingsManager.userVariantColor} type={Type.TERT} onPointerDown={e => e.stopPropagation()} placement={'top-end'} popup={this.popup} />
             </div>
         );
     }
-- 
cgit v1.2.3-70-g09d2


From fdaf11b65b0a4b729c2c08fff24a6802ebba6674 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Fri, 8 Sep 2023 11:45:12 -0400
Subject: fixed tab title flickering when hovering over a sidebar hyperlink
 when tab isn't selected.

---
 src/client/views/collections/TabDocView.tsx | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'src/client/views/collections/TabDocView.tsx')

diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx
index 0044a2832..9ea1ed2de 100644
--- a/src/client/views/collections/TabDocView.tsx
+++ b/src/client/views/collections/TabDocView.tsx
@@ -475,7 +475,7 @@ export class TabDocView extends React.Component<TabDocViewProps> {
                 style={{
                     fontFamily: Doc.UserDoc().renderStyle === 'comic' ? 'Comic Sans MS' : undefined,
                 }}
-                onPointerEnter={action(() => (this._hovering = true))}
+                onPointerOver={action(() => (this._hovering = true))}
                 onPointerLeave={action(() => (this._hovering = false))}
                 onDragOver={action(() => (this._hovering = true))}
                 onDragLeave={action(() => (this._hovering = false))}
-- 
cgit v1.2.3-70-g09d2


From 888ddd78737781f8a2d045b5f1e41788c512c94d Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Fri, 8 Sep 2023 17:02:49 -0400
Subject: don't remove current recording from overlay, added closeOnSelect
 option  for dropdown.   place recording box on screen.  fixe overlayView to
 keep views on screen. fixed schema view checkboxes. don't cause tab to
 rerender when colelctoin type changes.  add dropdown to filter indicator to
 find filters.

---
 package-lock.json                                  | 166 +++++++++++++--------
 package.json                                       |   2 +-
 src/client/util/CurrentUserUtils.ts                |   1 -
 src/client/util/SettingsManager.tsx                |   6 +-
 src/client/util/reportManager/ReportManager.tsx    |   2 +
 src/client/views/DashboardView.tsx                 |   1 +
 src/client/views/MainView.tsx                      |   6 +-
 src/client/views/OverlayView.tsx                   |  15 ++
 src/client/views/PropertiesButtons.tsx             |   1 +
 src/client/views/PropertiesView.tsx                |  39 +++--
 src/client/views/StyleProvider.scss                |   9 +-
 src/client/views/StyleProvider.tsx                 |  41 ++++-
 src/client/views/UndoStack.tsx                     |  12 +-
 src/client/views/collections/TabDocView.tsx        |  10 +-
 .../collectionSchema/CollectionSchemaView.tsx      |   8 +-
 src/client/views/nodes/FontIconBox/FontIconBox.tsx |   3 +-
 .../views/nodes/RecordingBox/RecordingBox.tsx      |   9 +-
 17 files changed, 213 insertions(+), 118 deletions(-)

(limited to 'src/client/views/collections/TabDocView.tsx')

diff --git a/package-lock.json b/package-lock.json
index b6c03c6ba..6055e9d1e 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -142,20 +142,20 @@
             "integrity": "sha512-5UamI7xkUcJ3i9qVDS+KFDEK8/7oJ55/sJMB1Ge7IEapr7KfdfV/HErR+koZwOfd+SgtFKOKRhRakdg++DcJpQ=="
         },
         "@babel/core": {
-            "version": "7.22.15",
-            "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.22.15.tgz",
-            "integrity": "sha512-PtZqMmgRrvj8ruoEOIwVA3yoF91O+Hgw9o7DAUTNBA6Mo2jpu31clx9a7Nz/9JznqetTR6zwfC4L3LAjKQXUwA==",
+            "version": "7.22.17",
+            "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.22.17.tgz",
+            "integrity": "sha512-2EENLmhpwplDux5PSsZnSbnSkB3tZ6QTksgO25xwEL7pIDcNOMhF5v/s6RzwjMZzZzw9Ofc30gHv5ChCC8pifQ==",
             "requires": {
                 "@ampproject/remapping": "^2.2.0",
                 "@babel/code-frame": "^7.22.13",
                 "@babel/generator": "^7.22.15",
                 "@babel/helper-compilation-targets": "^7.22.15",
-                "@babel/helper-module-transforms": "^7.22.15",
+                "@babel/helper-module-transforms": "^7.22.17",
                 "@babel/helpers": "^7.22.15",
-                "@babel/parser": "^7.22.15",
+                "@babel/parser": "^7.22.16",
                 "@babel/template": "^7.22.15",
-                "@babel/traverse": "^7.22.15",
-                "@babel/types": "^7.22.15",
+                "@babel/traverse": "^7.22.17",
+                "@babel/types": "^7.22.17",
                 "convert-source-map": "^1.7.0",
                 "debug": "^4.1.0",
                 "gensync": "^1.0.0-beta.2",
@@ -209,9 +209,9 @@
                     }
                 },
                 "@babel/traverse": {
-                    "version": "7.22.15",
-                    "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.15.tgz",
-                    "integrity": "sha512-DdHPwvJY0sEeN4xJU5uRLmZjgMMDIvMPniLuYzUVXj/GGzysPl0/fwt44JBkyUIzGJPV8QgHMcQdQ34XFuKTYQ==",
+                    "version": "7.22.17",
+                    "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.17.tgz",
+                    "integrity": "sha512-xK4Uwm0JnAMvxYZxOVecss85WxTEIbTa7bnGyf/+EgCL5Zt3U7htUpEOWv9detPlamGKuRzCqw74xVglDWpPdg==",
                     "requires": {
                         "@babel/code-frame": "^7.22.13",
                         "@babel/generator": "^7.22.15",
@@ -219,16 +219,16 @@
                         "@babel/helper-function-name": "^7.22.5",
                         "@babel/helper-hoist-variables": "^7.22.5",
                         "@babel/helper-split-export-declaration": "^7.22.6",
-                        "@babel/parser": "^7.22.15",
-                        "@babel/types": "^7.22.15",
+                        "@babel/parser": "^7.22.16",
+                        "@babel/types": "^7.22.17",
                         "debug": "^4.1.0",
                         "globals": "^11.1.0"
                     }
                 },
                 "@babel/types": {
-                    "version": "7.22.15",
-                    "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.15.tgz",
-                    "integrity": "sha512-X+NLXr0N8XXmN5ZsaQdm9U2SSC3UbIYq/doL++sueHOTisgZHoKaQtZxGuV2cUPQHMfjKEfg/g6oy7Hm6SKFtA==",
+                    "version": "7.22.17",
+                    "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.17.tgz",
+                    "integrity": "sha512-YSQPHLFtQNE5xN9tHuZnzu8vPr61wVTBZdfv1meex1NBosa4iT05k/Jw06ddJugi4bk7The/oSwQGFcksmEJQg==",
                     "requires": {
                         "@babel/helper-string-parser": "^7.22.5",
                         "@babel/helper-validator-identifier": "^7.22.15",
@@ -300,9 +300,9 @@
                     "integrity": "sha512-4E/F9IIEi8WR94324mbDUMo074YTheJmd7eZF5vITTeYchqAi6sYXRLHUVsmkdmY4QjfKTcB2jB7dVP3NaBElQ=="
                 },
                 "@babel/types": {
-                    "version": "7.22.15",
-                    "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.15.tgz",
-                    "integrity": "sha512-X+NLXr0N8XXmN5ZsaQdm9U2SSC3UbIYq/doL++sueHOTisgZHoKaQtZxGuV2cUPQHMfjKEfg/g6oy7Hm6SKFtA==",
+                    "version": "7.22.17",
+                    "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.17.tgz",
+                    "integrity": "sha512-YSQPHLFtQNE5xN9tHuZnzu8vPr61wVTBZdfv1meex1NBosa4iT05k/Jw06ddJugi4bk7The/oSwQGFcksmEJQg==",
                     "requires": {
                         "@babel/helper-string-parser": "^7.22.5",
                         "@babel/helper-validator-identifier": "^7.22.15",
@@ -472,9 +472,9 @@
                     "integrity": "sha512-4E/F9IIEi8WR94324mbDUMo074YTheJmd7eZF5vITTeYchqAi6sYXRLHUVsmkdmY4QjfKTcB2jB7dVP3NaBElQ=="
                 },
                 "@babel/types": {
-                    "version": "7.22.15",
-                    "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.15.tgz",
-                    "integrity": "sha512-X+NLXr0N8XXmN5ZsaQdm9U2SSC3UbIYq/doL++sueHOTisgZHoKaQtZxGuV2cUPQHMfjKEfg/g6oy7Hm6SKFtA==",
+                    "version": "7.22.17",
+                    "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.17.tgz",
+                    "integrity": "sha512-YSQPHLFtQNE5xN9tHuZnzu8vPr61wVTBZdfv1meex1NBosa4iT05k/Jw06ddJugi4bk7The/oSwQGFcksmEJQg==",
                     "requires": {
                         "@babel/helper-string-parser": "^7.22.5",
                         "@babel/helper-validator-identifier": "^7.22.15",
@@ -492,9 +492,9 @@
             }
         },
         "@babel/helper-module-transforms": {
-            "version": "7.22.15",
-            "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.22.15.tgz",
-            "integrity": "sha512-l1UiX4UyHSFsYt17iQ3Se5pQQZZHa22zyIXURmvkmLCD4t/aU+dvNWHatKac/D9Vm9UES7nvIqHs4jZqKviUmQ==",
+            "version": "7.22.17",
+            "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.22.17.tgz",
+            "integrity": "sha512-XouDDhQESrLHTpnBtCKExJdyY4gJCdrvH2Pyv8r8kovX2U8G0dRUOT45T9XlbLtuu9CLXP15eusnkprhoPV5iQ==",
             "requires": {
                 "@babel/helper-environment-visitor": "^7.22.5",
                 "@babel/helper-module-imports": "^7.22.15",
@@ -517,9 +517,9 @@
                     "integrity": "sha512-4E/F9IIEi8WR94324mbDUMo074YTheJmd7eZF5vITTeYchqAi6sYXRLHUVsmkdmY4QjfKTcB2jB7dVP3NaBElQ=="
                 },
                 "@babel/types": {
-                    "version": "7.22.15",
-                    "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.15.tgz",
-                    "integrity": "sha512-X+NLXr0N8XXmN5ZsaQdm9U2SSC3UbIYq/doL++sueHOTisgZHoKaQtZxGuV2cUPQHMfjKEfg/g6oy7Hm6SKFtA==",
+                    "version": "7.22.17",
+                    "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.17.tgz",
+                    "integrity": "sha512-YSQPHLFtQNE5xN9tHuZnzu8vPr61wVTBZdfv1meex1NBosa4iT05k/Jw06ddJugi4bk7The/oSwQGFcksmEJQg==",
                     "requires": {
                         "@babel/helper-string-parser": "^7.22.5",
                         "@babel/helper-validator-identifier": "^7.22.15",
@@ -542,13 +542,13 @@
             "integrity": "sha512-8RvlJG2mj4huQ4pZ+rU9lqKi9ZKiRmuvGuM2HlWmkmgOhbs6zEAw6IEiJ5cQqGbDzGZOhwuOQNtZMi/ENLjZoQ=="
         },
         "@babel/helper-remap-async-to-generator": {
-            "version": "7.22.9",
-            "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.22.9.tgz",
-            "integrity": "sha512-8WWC4oR4Px+tr+Fp0X3RHDVfINGpF3ad1HIbrc8A77epiR6eMMc6jsgozkzT2uDiOOdoS9cLIQ+XD2XvI2WSmQ==",
+            "version": "7.22.17",
+            "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.22.17.tgz",
+            "integrity": "sha512-bxH77R5gjH3Nkde6/LuncQoLaP16THYPscurp1S8z7S9ZgezCyV3G8Hc+TZiCmY8pz4fp8CvKSgtJMW0FkLAxA==",
             "requires": {
                 "@babel/helper-annotate-as-pure": "^7.22.5",
                 "@babel/helper-environment-visitor": "^7.22.5",
-                "@babel/helper-wrap-function": "^7.22.9"
+                "@babel/helper-wrap-function": "^7.22.17"
             },
             "dependencies": {
                 "@babel/helper-annotate-as-pure": {
@@ -611,28 +611,64 @@
             "integrity": "sha512-bMn7RmyFjY/mdECUbgn9eoSY4vqvacUnS9i9vGAGttgFWesO6B4CYWA7XlpbWgBt71iv/hfbPlynohStqnu5hA=="
         },
         "@babel/helper-wrap-function": {
-            "version": "7.22.10",
-            "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.22.10.tgz",
-            "integrity": "sha512-OnMhjWjuGYtdoO3FmsEFWvBStBAe2QOgwOLsLNDjN+aaiMD8InJk1/O3HSD8lkqTjCgg5YI34Tz15KNNA3p+nQ==",
+            "version": "7.22.17",
+            "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.22.17.tgz",
+            "integrity": "sha512-nAhoheCMlrqU41tAojw9GpVEKDlTS8r3lzFmF0lP52LwblCPbuFSO7nGIZoIcoU5NIm1ABrna0cJExE4Ay6l2Q==",
             "requires": {
                 "@babel/helper-function-name": "^7.22.5",
-                "@babel/template": "^7.22.5",
-                "@babel/types": "^7.22.10"
+                "@babel/template": "^7.22.15",
+                "@babel/types": "^7.22.17"
             },
             "dependencies": {
-                "@babel/helper-validator-identifier": {
+                "@babel/code-frame": {
+                    "version": "7.22.13",
+                    "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz",
+                    "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==",
+                    "requires": {
+                        "@babel/highlight": "^7.22.13",
+                        "chalk": "^2.4.2"
+                    }
+                },
+                "@babel/highlight": {
+                    "version": "7.22.13",
+                    "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.13.tgz",
+                    "integrity": "sha512-C/BaXcnnvBCmHTpz/VGZ8jgtE2aYlW4hxDhseJAWZb7gqGM/qtCK6iZUb0TyKFf7BOUsBH7Q7fkRsDRhg1XklQ==",
+                    "requires": {
+                        "@babel/helper-validator-identifier": "^7.22.5",
+                        "chalk": "^2.4.2",
+                        "js-tokens": "^4.0.0"
+                    }
+                },
+                "@babel/parser": {
+                    "version": "7.22.16",
+                    "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.16.tgz",
+                    "integrity": "sha512-+gPfKv8UWeKKeJTUxe59+OobVcrYHETCsORl61EmSkmgymguYk/X5bp7GuUIXaFsc6y++v8ZxPsLSSuujqDphA=="
+                },
+                "@babel/template": {
                     "version": "7.22.15",
-                    "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.15.tgz",
-                    "integrity": "sha512-4E/F9IIEi8WR94324mbDUMo074YTheJmd7eZF5vITTeYchqAi6sYXRLHUVsmkdmY4QjfKTcB2jB7dVP3NaBElQ=="
+                    "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz",
+                    "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==",
+                    "requires": {
+                        "@babel/code-frame": "^7.22.13",
+                        "@babel/parser": "^7.22.15",
+                        "@babel/types": "^7.22.15"
+                    }
                 },
                 "@babel/types": {
-                    "version": "7.22.15",
-                    "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.15.tgz",
-                    "integrity": "sha512-X+NLXr0N8XXmN5ZsaQdm9U2SSC3UbIYq/doL++sueHOTisgZHoKaQtZxGuV2cUPQHMfjKEfg/g6oy7Hm6SKFtA==",
+                    "version": "7.22.17",
+                    "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.17.tgz",
+                    "integrity": "sha512-YSQPHLFtQNE5xN9tHuZnzu8vPr61wVTBZdfv1meex1NBosa4iT05k/Jw06ddJugi4bk7The/oSwQGFcksmEJQg==",
                     "requires": {
                         "@babel/helper-string-parser": "^7.22.5",
                         "@babel/helper-validator-identifier": "^7.22.15",
                         "to-fast-properties": "^2.0.0"
+                    },
+                    "dependencies": {
+                        "@babel/helper-validator-identifier": {
+                            "version": "7.22.15",
+                            "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.15.tgz",
+                            "integrity": "sha512-4E/F9IIEi8WR94324mbDUMo074YTheJmd7eZF5vITTeYchqAi6sYXRLHUVsmkdmY4QjfKTcB2jB7dVP3NaBElQ=="
+                        }
                     }
                 }
             }
@@ -693,9 +729,9 @@
                     }
                 },
                 "@babel/traverse": {
-                    "version": "7.22.15",
-                    "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.15.tgz",
-                    "integrity": "sha512-DdHPwvJY0sEeN4xJU5uRLmZjgMMDIvMPniLuYzUVXj/GGzysPl0/fwt44JBkyUIzGJPV8QgHMcQdQ34XFuKTYQ==",
+                    "version": "7.22.17",
+                    "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.17.tgz",
+                    "integrity": "sha512-xK4Uwm0JnAMvxYZxOVecss85WxTEIbTa7bnGyf/+EgCL5Zt3U7htUpEOWv9detPlamGKuRzCqw74xVglDWpPdg==",
                     "requires": {
                         "@babel/code-frame": "^7.22.13",
                         "@babel/generator": "^7.22.15",
@@ -703,16 +739,16 @@
                         "@babel/helper-function-name": "^7.22.5",
                         "@babel/helper-hoist-variables": "^7.22.5",
                         "@babel/helper-split-export-declaration": "^7.22.6",
-                        "@babel/parser": "^7.22.15",
-                        "@babel/types": "^7.22.15",
+                        "@babel/parser": "^7.22.16",
+                        "@babel/types": "^7.22.17",
                         "debug": "^4.1.0",
                         "globals": "^11.1.0"
                     }
                 },
                 "@babel/types": {
-                    "version": "7.22.15",
-                    "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.15.tgz",
-                    "integrity": "sha512-X+NLXr0N8XXmN5ZsaQdm9U2SSC3UbIYq/doL++sueHOTisgZHoKaQtZxGuV2cUPQHMfjKEfg/g6oy7Hm6SKFtA==",
+                    "version": "7.22.17",
+                    "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.17.tgz",
+                    "integrity": "sha512-YSQPHLFtQNE5xN9tHuZnzu8vPr61wVTBZdfv1meex1NBosa4iT05k/Jw06ddJugi4bk7The/oSwQGFcksmEJQg==",
                     "requires": {
                         "@babel/helper-string-parser": "^7.22.5",
                         "@babel/helper-validator-identifier": "^7.22.15",
@@ -1691,9 +1727,9 @@
                     }
                 },
                 "@babel/types": {
-                    "version": "7.22.15",
-                    "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.15.tgz",
-                    "integrity": "sha512-X+NLXr0N8XXmN5ZsaQdm9U2SSC3UbIYq/doL++sueHOTisgZHoKaQtZxGuV2cUPQHMfjKEfg/g6oy7Hm6SKFtA==",
+                    "version": "7.22.17",
+                    "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.17.tgz",
+                    "integrity": "sha512-YSQPHLFtQNE5xN9tHuZnzu8vPr61wVTBZdfv1meex1NBosa4iT05k/Jw06ddJugi4bk7The/oSwQGFcksmEJQg==",
                     "requires": {
                         "@babel/helper-string-parser": "^7.22.5",
                         "@babel/helper-validator-identifier": "^7.22.15",
@@ -2028,9 +2064,9 @@
                     "integrity": "sha512-4E/F9IIEi8WR94324mbDUMo074YTheJmd7eZF5vITTeYchqAi6sYXRLHUVsmkdmY4QjfKTcB2jB7dVP3NaBElQ=="
                 },
                 "@babel/types": {
-                    "version": "7.22.15",
-                    "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.15.tgz",
-                    "integrity": "sha512-X+NLXr0N8XXmN5ZsaQdm9U2SSC3UbIYq/doL++sueHOTisgZHoKaQtZxGuV2cUPQHMfjKEfg/g6oy7Hm6SKFtA==",
+                    "version": "7.22.17",
+                    "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.17.tgz",
+                    "integrity": "sha512-YSQPHLFtQNE5xN9tHuZnzu8vPr61wVTBZdfv1meex1NBosa4iT05k/Jw06ddJugi4bk7The/oSwQGFcksmEJQg==",
                     "requires": {
                         "@babel/helper-string-parser": "^7.22.5",
                         "@babel/helper-validator-identifier": "^7.22.15",
@@ -6651,9 +6687,9 @@
             }
         },
         "browndash-components": {
-            "version": "0.1.23",
-            "resolved": "https://registry.npmjs.org/browndash-components/-/browndash-components-0.1.23.tgz",
-            "integrity": "sha512-yZPnSUBXdToufaq4mTYHMgDwrijQWsuVKK8j+NilRKMqmOrkZeqyRhncTDz077DcMLcjeIj+SobT3GPK04TXmQ==",
+            "version": "0.1.25",
+            "resolved": "https://registry.npmjs.org/browndash-components/-/browndash-components-0.1.25.tgz",
+            "integrity": "sha512-YgzUsfeUKwtaOLRYNDcxybZG2Ip7KSQV38VbUrgC+ycwOX/tzq9IWlfw2z4h/EVuVcq+ERCaBS4pb3mMU6pKGQ==",
             "requires": {
                 "@emotion/react": "^11.11.1",
                 "@emotion/styled": "^11.11.0",
@@ -10110,14 +10146,14 @@
                     }
                 },
                 "caniuse-lite": {
-                    "version": "1.0.30001528",
-                    "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001528.tgz",
-                    "integrity": "sha512-0Db4yyjR9QMNlsxh+kKWzQtkyflkG/snYheSzkjmvdEtEXB1+jt7A2HmSEiO6XIJPIbo92lHNGNySvE5pZcs5Q=="
+                    "version": "1.0.30001529",
+                    "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001529.tgz",
+                    "integrity": "sha512-n2pUQYGAkrLG4QYj2desAh+NqsJpHbNmVZz87imptDdxLAtjxary7Df/psdfyDGmskJK/9Dt9cPnx5RZ3CU4Og=="
                 },
                 "electron-to-chromium": {
-                    "version": "1.4.510",
-                    "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.510.tgz",
-                    "integrity": "sha512-xPfLIPFcN/WLXBpQ/K4UgE98oUBO5Tia6BD4rkSR0wE7ep/PwBVlgvPJQrIBpmJGVAmUzwPKuDbVt9XV6+uC2g=="
+                    "version": "1.4.513",
+                    "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.513.tgz",
+                    "integrity": "sha512-cOB0xcInjm+E5qIssHeXJ29BaUyWpMyFKT5RB3bsLENDheCja0wMkHJyiPl0NBE/VzDI7JDuNEQWhe6RitEUcw=="
                 }
             }
         },
diff --git a/package.json b/package.json
index c218d80ff..9f0b91628 100644
--- a/package.json
+++ b/package.json
@@ -178,7 +178,7 @@
         "body-parser": "^1.19.2",
         "bootstrap": "^4.6.1",
         "brotli": "^1.3.3",
-        "browndash-components": "^0.1.23",
+        "browndash-components": "^0.1.25",
         "browser-assert": "^1.2.1",
         "bson": "^4.6.1",
         "canvas": "^2.9.3",
diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index aa5f2658a..8bedea562 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -763,7 +763,6 @@ export class CurrentUserUtils {
     }
     /// Initializes all the default buttons for the top bar context menu
     static setupTopbarButtons(doc: Doc, field="myTopBarBtns") {
-        if (Doc.UserDoc().currentRecording) Doc.RemFromMyOverlay(DocCast(Doc.UserDoc().currentRecording));
         Doc.UserDoc().currentRecording = undefined;
         Doc.UserDoc().workspaceRecordingState = undefined;
         Doc.UserDoc().workspaceReplayingState = undefined;
diff --git a/src/client/util/SettingsManager.tsx b/src/client/util/SettingsManager.tsx
index 720badd40..53cfbc947 100644
--- a/src/client/util/SettingsManager.tsx
+++ b/src/client/util/SettingsManager.tsx
@@ -142,6 +142,7 @@ export class SettingsManager extends React.Component<{}> {
                     formLabel="Theme"
                     size={Size.SMALL}
                     type={Type.TERT}
+                    closeOnSelect={false}
                     selectedVal={userTheme}
                     setSelectedVal={scheme => this.changeColorScheme(scheme as string)}
                     items={colorSchemes.map((scheme, i) => ({
@@ -294,6 +295,7 @@ export class SettingsManager extends React.Component<{}> {
                                         },
                                     };
                                 })}
+                                closeOnSelect={true}
                                 dropdownType={DropdownType.SELECT}
                                 type={Type.TERT}
                                 selectedVal={StrCast(Doc.UserDoc().fontFamily)}
@@ -373,6 +375,7 @@ export class SettingsManager extends React.Component<{}> {
                     <div className="tab-column-content">
                         <Dropdown
                             formLabel={'Mode'}
+                            closeOnSelect={true}
                             items={[
                                 {
                                     text: 'Novice',
@@ -403,7 +406,8 @@ export class SettingsManager extends React.Component<{}> {
                     </div>
                     <div className="tab-column-content">
                         <Dropdown
-                            formLabel={'Scroll Mode'}
+                            formLabel="Scroll Mode"
+                            closeOnSelect={true}
                             items={[
                                 {
                                     text: 'Scroll to Pan',
diff --git a/src/client/util/reportManager/ReportManager.tsx b/src/client/util/reportManager/ReportManager.tsx
index 6a236face..08467448d 100644
--- a/src/client/util/reportManager/ReportManager.tsx
+++ b/src/client/util/reportManager/ReportManager.tsx
@@ -308,6 +308,7 @@ export class ReportManager extends React.Component<{}> {
                     <Dropdown
                         color={StrCast(Doc.UserDoc().userColor)}
                         formLabel={'Type'}
+                        closeOnSelect={true}
                         items={bugDropdownItems}
                         selectedVal={this.formData.type}
                         setSelectedVal={val => {
@@ -320,6 +321,7 @@ export class ReportManager extends React.Component<{}> {
                     <Dropdown
                         color={StrCast(Doc.UserDoc().userColor)}
                         formLabel={'Priority'}
+                        closeOnSelect={true}
                         items={priorityDropdownItems}
                         selectedVal={this.formData.priority}
                         setSelectedVal={val => {
diff --git a/src/client/views/DashboardView.tsx b/src/client/views/DashboardView.tsx
index 1d1d0eaab..014a6358f 100644
--- a/src/client/views/DashboardView.tsx
+++ b/src/client/views/DashboardView.tsx
@@ -371,6 +371,7 @@ export class DashboardView extends React.Component {
 
         Doc.AddDocToList(Doc.MyHeaderBar, 'data', freeformDoc);
         dashboardDoc['pane-count'] = 1;
+        freeformDoc.embedContainer = dashboardDoc;
 
         Doc.AddDocToList(Doc.MyDashboards, 'data', dashboardDoc);
 
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 8adb28fe1..2b4f4d5f7 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -810,7 +810,11 @@ export class MainView extends React.Component {
                             </div>
                         )}
                         <div className="properties-container" style={{ width: this.propertiesWidth(), color: SettingsManager.userColor }}>
-                            {this.propertiesWidth() < 10 ? null : <PropertiesView styleProvider={DefaultStyleProvider} addDocTab={DocumentViewInternal.addDocTabFunc} width={this.propertiesWidth()} height={this.propertiesHeight()} />}
+                            {
+                                <div style={{ display: this.propertiesWidth() < 10 ? 'none' : undefined }}>
+                                    <PropertiesView styleProvider={DefaultStyleProvider} addDocTab={DocumentViewInternal.addDocTabFunc} width={this.propertiesWidth()} height={this.propertiesHeight()} />
+                                </div>
+                            }
                         </div>
                     </div>
                 </div>
diff --git a/src/client/views/OverlayView.tsx b/src/client/views/OverlayView.tsx
index 5d95c5fda..c174befc0 100644
--- a/src/client/views/OverlayView.tsx
+++ b/src/client/views/OverlayView.tsx
@@ -16,6 +16,7 @@ import { LightboxView } from './LightboxView';
 import { DocumentView, DocumentViewInternal } from './nodes/DocumentView';
 import './OverlayView.scss';
 import { DefaultStyleProvider } from './StyleProvider';
+const _global = (window /* browser */ || global) /* node */ as any;
 
 export type OverlayDisposer = () => void;
 
@@ -115,6 +116,20 @@ export class OverlayView extends React.Component {
         super(props);
         if (!OverlayView.Instance) {
             OverlayView.Instance = this;
+            new _global.ResizeObserver(
+                action((entries: any) => {
+                    for (const entry of entries) {
+                        DocListCast(Doc.MyOverlayDocs?.data).forEach(doc => {
+                            if (NumCast(doc.overlayX) > entry.contentRect.width - 10) {
+                                doc.overlayX = entry.contentRect.width - 10;
+                            }
+                            if (NumCast(doc.overlayY) > entry.contentRect.height - 10) {
+                                doc.overlayY = entry.contentRect.height - 10;
+                            }
+                        });
+                    }
+                })
+            ).observe(window.document.body);
         }
     }
 
diff --git a/src/client/views/PropertiesButtons.tsx b/src/client/views/PropertiesButtons.tsx
index 42db0b9be..d939470e9 100644
--- a/src/client/views/PropertiesButtons.tsx
+++ b/src/client/views/PropertiesButtons.tsx
@@ -376,6 +376,7 @@ export class PropertiesButtons extends React.Component<{}, {}> {
             <Dropdown
                 tooltip={'Choose onClick behavior'}
                 items={items}
+                closeOnSelect={true}
                 selectedVal={this.onClickVal}
                 setSelectedVal={val => this.handleOptionChange(val as string)}
                 title={'Choose onClick behaviour'}
diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx
index 72ff906f6..9cc75b1c6 100644
--- a/src/client/views/PropertiesView.tsx
+++ b/src/client/views/PropertiesView.tsx
@@ -52,6 +52,12 @@ interface PropertiesViewProps {
 export class PropertiesView extends React.Component<PropertiesViewProps> {
     private _widthUndo?: UndoManager.Batch;
 
+    public static Instance: PropertiesView | undefined;
+    constructor(props: any) {
+        super(props);
+        PropertiesView.Instance = this;
+    }
+
     @computed get MAX_EMBED_HEIGHT() {
         return 200;
     }
@@ -75,6 +81,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
     }
 
     @observable layoutFields: boolean = false;
+    @observable layoutDocAcls: boolean = false;
 
     @observable openOptions: boolean = true;
     @observable openSharing: boolean = true;
@@ -86,8 +93,6 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
     @observable openTransform: boolean = true;
     @observable openFilters: boolean = false;
 
-    @observable layoutDocAcls: boolean = false;
-
     //Pres Trails booleans:
     @observable openPresTransitions: boolean = true;
     @observable openPresProgressivize: boolean = false;
@@ -103,7 +108,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
         this._disposers.link = reaction(
             () => LinkManager.currentLink,
             link => {
-                link && this.onDoubleClick();
+                link && this.CloseAll();
                 link && (this.openLinks = true);
             },
             { fireImmediately: true }
@@ -970,7 +975,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
     };
 
     @action
-    onDoubleClick = () => {
+    CloseAll = () => {
         this.openContexts = false;
         this.openLinks = false;
         this.openOptions = false;
@@ -1120,7 +1125,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
                 isOpen={this.openOptions}
                 setInSection={bool => (this.inOptions = bool)}
                 setIsOpen={bool => (this.openOptions = bool)}
-                onDoubleClick={this.onDoubleClick}
+                onDoubleClick={this.CloseAll}
             />
         );
     }
@@ -1147,7 +1152,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
                 }
                 isOpen={this.openSharing}
                 setIsOpen={bool => (this.openSharing = bool)}
-                onDoubleClick={() => this.onDoubleClick()}
+                onDoubleClick={() => this.CloseAll()}
             />
         );
     }
@@ -1187,7 +1192,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
                 }
                 isOpen={this.openFilters}
                 setIsOpen={bool => (this.openFilters = bool)}
-                onDoubleClick={() => this.onDoubleClick()}
+                onDoubleClick={() => this.CloseAll()}
             />
         );
     }
@@ -1197,8 +1202,8 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
 
         return (
             <>
-                <PropertiesSection title="Appearance" content={this.isInk ? this.appearanceEditor : null} isOpen={this.openAppearance} setIsOpen={bool => (this.openAppearance = bool)} onDoubleClick={() => this.onDoubleClick()} />
-                <PropertiesSection title="Transform" content={this.transformEditor} isOpen={this.openTransform} setIsOpen={bool => (this.openTransform = bool)} onDoubleClick={() => this.onDoubleClick()} />
+                <PropertiesSection title="Appearance" content={this.isInk ? this.appearanceEditor : null} isOpen={this.openAppearance} setIsOpen={bool => (this.openAppearance = bool)} onDoubleClick={() => this.CloseAll()} />
+                <PropertiesSection title="Transform" content={this.transformEditor} isOpen={this.openTransform} setIsOpen={bool => (this.openTransform = bool)} onDoubleClick={() => this.CloseAll()} />
             </>
         );
     }
@@ -1210,29 +1215,23 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
                 content={<div className="propertiesView-content fields">{Doc.noviceMode ? this.noviceFields : this.expandedField}</div>}
                 isOpen={this.openFields}
                 setIsOpen={bool => (this.openFields = bool)}
-                onDoubleClick={() => this.onDoubleClick()}
+                onDoubleClick={() => this.CloseAll()}
             />
         );
     }
 
     @computed get contextsSubMenu() {
         return (
-            <PropertiesSection
-                title="Other Contexts"
-                content={this.contextCount > 0 ? this.contexts : 'There are no other contexts.'}
-                isOpen={this.openContexts}
-                setIsOpen={bool => (this.openContexts = bool)}
-                onDoubleClick={() => this.onDoubleClick()}
-            />
+            <PropertiesSection title="Other Contexts" content={this.contextCount > 0 ? this.contexts : 'There are no other contexts.'} isOpen={this.openContexts} setIsOpen={bool => (this.openContexts = bool)} onDoubleClick={() => this.CloseAll()} />
         );
     }
 
     @computed get linksSubMenu() {
-        return <PropertiesSection title="Linked To" content={this.linkCount > 0 ? this.links : 'There are no current links.'} isOpen={this.openLinks} setIsOpen={bool => (this.openLinks = bool)} onDoubleClick={this.onDoubleClick} />;
+        return <PropertiesSection title="Linked To" content={this.linkCount > 0 ? this.links : 'There are no current links.'} isOpen={this.openLinks} setIsOpen={bool => (this.openLinks = bool)} onDoubleClick={this.CloseAll} />;
     }
 
     @computed get layoutSubMenu() {
-        return <PropertiesSection title="Layout" content={this.layoutPreview} isOpen={this.openLayout} setIsOpen={bool => (this.openLayout = bool)} onDoubleClick={this.onDoubleClick} />;
+        return <PropertiesSection title="Layout" content={this.layoutPreview} isOpen={this.openLayout} setIsOpen={bool => (this.openLayout = bool)} onDoubleClick={this.CloseAll} />;
     }
 
     @computed get description() {
@@ -1723,7 +1722,7 @@ export class PropertiesView extends React.Component<PropertiesViewProps> {
                         {this.contextsSubMenu}
                         {this.fieldsSubMenu}
                         {isNovice ? null : this.sharingSubMenu}
-                        {isNovice ? null : this.filtersSubMenu}
+                        {this.filtersSubMenu}
                         {isNovice ? null : this.layoutSubMenu}
                     </div>
                 );
diff --git a/src/client/views/StyleProvider.scss b/src/client/views/StyleProvider.scss
index c06bb287e..f069e7e1b 100644
--- a/src/client/views/StyleProvider.scss
+++ b/src/client/views/StyleProvider.scss
@@ -18,10 +18,15 @@
     cursor: default;
 }
 .styleProvider-filter {
-    right: 0;
+    right: 15;
+    .styleProvider-filterShift {
+        left: 0;
+        top: 0;
+        position: absolute;
+    }
 }
 .styleProvider-audio {
-    right: 15;
+    right: 30;
 }
 .styleProvider-lock:hover,
 .styleProvider-audio:hover,
diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx
index 069bfd049..8a5ad3139 100644
--- a/src/client/views/StyleProvider.tsx
+++ b/src/client/views/StyleProvider.tsx
@@ -1,7 +1,7 @@
 import { IconProp } from '@fortawesome/fontawesome-svg-core';
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import { Tooltip } from '@material-ui/core';
-import { IconButton, Shadows, Size } from 'browndash-components';
+import { Dropdown, DropdownType, IconButton, IListItemProps, ListBox, ListItem, Popup, Shadows, Size, Type } from 'browndash-components';
 import { action, runInAction } from 'mobx';
 import { extname } from 'path';
 import { BsArrowDown, BsArrowDownUp, BsArrowUp } from 'react-icons/bs';
@@ -24,6 +24,8 @@ import { KeyValueBox } from './nodes/KeyValueBox';
 import { SliderBox } from './nodes/SliderBox';
 import './StyleProvider.scss';
 import React = require('react');
+import { PropertiesView } from './PropertiesView';
+import { FaFilter } from 'react-icons/fa';
 
 export enum StyleProp {
     TreeViewIcon = 'treeView_Icon',
@@ -283,13 +285,44 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps
             const filter = () => {
                 const showFilterIcon =
                     StrListCast(doc?._childFilters).length || StrListCast(doc?._childFiltersByRanges).length
-                        ? '#18c718bd' //'hasFilter'
+                        ? 'green' // #18c718bd' //'hasFilter'
                         : docProps?.childFilters?.().filter(f => Utils.IsRecursiveFilter(f) && f !== Utils.noDragsDocFilter).length || docProps?.childFiltersByRanges().length
                         ? 'orange' //'inheritsFilter'
                         : undefined;
                 return !showFilterIcon ? null : (
-                    <div className="styleProvider-filter" onClick={action(() => (SettingsManager.propertiesWidth = 250))}>
-                        <FontAwesomeIcon icon={'filter'} size="lg" style={{ position: 'absolute', top: '1%', right: '1%', cursor: 'pointer', padding: 1, color: showFilterIcon, zIndex: 1 }} />
+                    <div className="styleProvider-filter">
+                        <Dropdown
+                            type={Type.TERT}
+                            dropdownType={DropdownType.CLICK}
+                            fillWidth
+                            iconProvider={(active:boolean) => <div className='styleProvider-filterShift'><FaFilter/></div>}
+                            closeOnSelect={true}
+                            setSelectedVal={
+                                action((dv) => {
+                                    (dv as any).select(false);
+                                    (SettingsManager.propertiesWidth = 250);
+                                    setTimeout(action(() => {
+                                        if (PropertiesView.Instance) {
+                                            PropertiesView.Instance.CloseAll();
+                                            PropertiesView.Instance.openFilters = true;
+                                        }
+                                    }));
+                                })
+                            }
+                            size={Size.XSMALL}
+                            width={15}
+                            height={15}
+                            title={showFilterIcon === 'green' ? 
+                                "This view is filtered.  Click to view/change filters":
+                                "this view inherits filters from one of its parents"}
+                            color={SettingsManager.userColor}
+                            background={showFilterIcon}
+                            items={[...(props?.docViewPath?.()??[]), ...(props?.DocumentView?[props?.DocumentView?.()]:[])].map(dv => ({
+                                text: StrCast(dv.rootDoc.title),
+                                val: dv as any,
+                                style: {color:SettingsManager.userColor, background:SettingsManager.userBackgroundColor},
+                            } as IListItemProps)) }
+                        />
                     </div>
                 );
             };
diff --git a/src/client/views/UndoStack.tsx b/src/client/views/UndoStack.tsx
index 1afd5ad22..093bb8b9c 100644
--- a/src/client/views/UndoStack.tsx
+++ b/src/client/views/UndoStack.tsx
@@ -1,14 +1,12 @@
-import { action, observable } from 'mobx';
+import { Tooltip } from '@mui/material';
+import { Popup, Type } from 'browndash-components';
+import { observable } from 'mobx';
 import { observer } from 'mobx-react';
 import * as React from 'react';
-import { UndoManager } from '../util/UndoManager';
-import './UndoStack.scss';
 import { StrCast } from '../../fields/Types';
-import { Doc } from '../../fields/Doc';
-import { Popup, Type, isDark } from 'browndash-components';
-import { Colors } from './global/globalEnums';
 import { SettingsManager } from '../util/SettingsManager';
-import { Tooltip } from '@mui/material';
+import { UndoManager } from '../util/UndoManager';
+import './UndoStack.scss';
 
 interface UndoStackProps {
     width?: number;
diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx
index 9ea1ed2de..d9faab063 100644
--- a/src/client/views/collections/TabDocView.tsx
+++ b/src/client/views/collections/TabDocView.tsx
@@ -17,6 +17,7 @@ import { CollectionViewType, DocumentType } from '../../documents/DocumentTypes'
 import { DocumentManager } from '../../util/DocumentManager';
 import { DragManager, dropActionType } from '../../util/DragManager';
 import { SelectionManager } from '../../util/SelectionManager';
+import { SettingsManager } from '../../util/SettingsManager';
 import { SnappingManager } from '../../util/SnappingManager';
 import { Transform } from '../../util/Transform';
 import { undoable, UndoManager } from '../../util/UndoManager';
@@ -33,7 +34,6 @@ import { CollectionFreeFormView } from './collectionFreeForm/CollectionFreeFormV
 import { CollectionView } from './CollectionView';
 import './TabDocView.scss';
 import React = require('react');
-import { SettingsManager } from '../../util/SettingsManager';
 const _global = (window /* browser */ || global) /* node */ as any;
 
 interface TabDocViewProps {
@@ -420,7 +420,7 @@ export class TabDocView extends React.Component<TabDocViewProps> {
     PanelHeight = () => this._panelHeight;
     miniMapColor = () => Colors.MEDIUM_GRAY;
     tabView = () => this._view;
-    disableMinimap = () => !this._document || this._document.layout !== CollectionView.LayoutString(Doc.LayoutFieldKey(this._document)) || this._document?._type_collection !== CollectionViewType.Freeform;
+    disableMinimap = () => !this._document;
     whenChildContentActiveChanges = (isActive: boolean) => (this._isAnyChildContentActive = isActive);
     isContentActive = () => this._isContentActive;
     waitForDoubleClick = () => (DocumentView.ExploreMode ? 'never' : undefined);
@@ -461,9 +461,7 @@ export class TabDocView extends React.Component<TabDocViewProps> {
                     bringToFront={emptyFunction}
                     pinToPres={TabDocView.PinDoc}
                 />
-                {this.disableMinimap() || this._document._type_collection !== CollectionViewType.Freeform ? null : (
-                    <TabMinimapView key="minimap" addDocTab={this.addDocTab} PanelHeight={this.PanelHeight} PanelWidth={this.PanelWidth} background={this.miniMapColor} document={this._document} tabView={this.tabView} />
-                )}
+                {this.disableMinimap() ? null : <TabMinimapView key="minimap" addDocTab={this.addDocTab} PanelHeight={this.PanelHeight} PanelWidth={this.PanelWidth} background={this.miniMapColor} document={this._document} tabView={this.tabView} />}
             </>
         );
     }
@@ -615,7 +613,7 @@ export class TabMinimapView extends React.Component<TabMinimapViewProps> {
         );
     };
     render() {
-        return (
+        return this.props.document.layout !== CollectionView.LayoutString(Doc.LayoutFieldKey(this.props.document)) || this.props.document?._type_collection !== CollectionViewType.Freeform ? null : (
             <div className="miniMap-hidden">
                 <Popup icon={<FontAwesomeIcon icon="globe-asia" size="lg" />} color={SettingsManager.userVariantColor} type={Type.TERT} onPointerDown={e => e.stopPropagation()} placement={'top-end'} popup={this.popup} />
             </div>
diff --git a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
index 182a33fd1..5c7dcc1a4 100644
--- a/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
+++ b/src/client/views/collections/collectionSchema/CollectionSchemaView.tsx
@@ -609,10 +609,10 @@ export class CollectionSchemaView extends CollectionSubView() {
         this._menuKeys = this.documentKeys.filter(value => value.toLowerCase().includes(this._menuValue.toLowerCase()));
     };
 
-    getFieldFilters = (field: string) => StrListCast(this.Document._childFilters).filter(filter => filter.split(':')[0] == field);
+    getFieldFilters = (field: string) => StrListCast(this.Document._childFilters).filter(filter => filter.split(Doc.FilterSep)[0] == field);
 
     removeFieldFilters = (field: string) => {
-        this.getFieldFilters(field).forEach(filter => Doc.setDocFilter(this.Document, field, filter.split(':')[1], 'remove'));
+        this.getFieldFilters(field).forEach(filter => Doc.setDocFilter(this.Document, field, filter.split(Doc.FilterSep)[1], 'remove'));
     };
 
     onFilterKeyDown = (e: React.KeyboardEvent) => {
@@ -766,8 +766,8 @@ export class CollectionSchemaView extends CollectionSubView() {
         return keyOptions.map(key => {
             let bool = false;
             if (filters !== undefined) {
-                const ind = filters.findIndex(filter => filter.split(':')[1] === key);
-                const fields = ind === -1 ? undefined : filters[ind].split(':');
+                const ind = filters.findIndex(filter => filter.split(Doc.FilterSep)[1] === key);
+                const fields = ind === -1 ? undefined : filters[ind].split(Doc.FilterSep);
                 bool = fields ? fields[2] === 'check' : false;
             }
             return (
diff --git a/src/client/views/nodes/FontIconBox/FontIconBox.tsx b/src/client/views/nodes/FontIconBox/FontIconBox.tsx
index 1eb6fd51c..0a59818ad 100644
--- a/src/client/views/nodes/FontIconBox/FontIconBox.tsx
+++ b/src/client/views/nodes/FontIconBox/FontIconBox.tsx
@@ -246,10 +246,11 @@ export class FontIconBox extends DocComponent<ButtonProps>() {
         return (
             <Dropdown
                 selectedVal={text}
-                setSelectedVal={undoable(val => script.script.run({ this: this.layoutDoc, self: this.rootDoc, val }), `dropdown select ${this.label}`)}
+                setSelectedVal={undoable(value => script.script.run({ this: this.layoutDoc, self: this.rootDoc, value }), `dropdown select ${this.label}`)}
                 color={SettingsManager.userColor}
                 background={SettingsManager.userVariantColor}
                 type={Type.TERT}
+                closeOnSelect={false}
                 dropdownType={DropdownType.SELECT}
                 onItemDown={this.dropdownItemDown}
                 items={list}
diff --git a/src/client/views/nodes/RecordingBox/RecordingBox.tsx b/src/client/views/nodes/RecordingBox/RecordingBox.tsx
index 1f113110b..481e43feb 100644
--- a/src/client/views/nodes/RecordingBox/RecordingBox.tsx
+++ b/src/client/views/nodes/RecordingBox/RecordingBox.tsx
@@ -119,7 +119,7 @@ export class RecordingBox extends ViewBoxBaseComponent<FieldViewProps>() {
     public static replayWorkspace(value: Doc) {
         Doc.UserDoc().currentRecording = value;
         value.overlayX = 70;
-        value.overlayY = 590;
+        value.overlayY = window.innerHeight - 180;
         Doc.AddToMyOverlay(value);
         DocumentManager.Instance.AddViewRenderedCb(value, docView => {
             Doc.UserDoc().currentRecording = docView.rootDoc;
@@ -147,11 +147,10 @@ export class RecordingBox extends ViewBoxBaseComponent<FieldViewProps>() {
     @action
     public static resumeWorkspaceReplaying(doc: Doc) {
         const docView = DocumentManager.Instance.getDocumentView(doc);
-        const videoBox = docView?.ComponentView as VideoBox;
-        if (videoBox) {
-            videoBox.Play();
-            Doc.UserDoc().workspaceReplayingState = media_state.Playing;
+        if (docView?.ComponentView instanceof VideoBox) {
+            docView.ComponentView.Play();
         }
+        Doc.UserDoc().workspaceReplayingState = media_state.Playing;
     }
 
     @action
-- 
cgit v1.2.3-70-g09d2


From 542f641ccd026c99912e864b47186f189410b280 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Wed, 13 Sep 2023 12:29:19 -0400
Subject: fixed region highlight when dragging minimap

---
 src/client/views/collections/TabDocView.tsx        | 53 ++++++++++++----------
 .../collectionFreeForm/CollectionFreeFormView.tsx  |  2 +-
 2 files changed, 30 insertions(+), 25 deletions(-)

(limited to 'src/client/views/collections/TabDocView.tsx')

diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx
index d9faab063..dab53b671 100644
--- a/src/client/views/collections/TabDocView.tsx
+++ b/src/client/views/collections/TabDocView.tsx
@@ -502,6 +502,18 @@ interface TabMinimapViewProps {
     PanelHeight: () => number;
     background: () => string;
 }
+interface TabMiniThumbProps {
+    miniWidth: () => number;
+    miniHeight: () => number;
+    miniTop: () => number;
+    miniLeft: () => number;
+}
+@observer
+class TabMiniThumb extends React.Component<TabMiniThumbProps> {
+    render() {
+        return <div className="miniThumb" style={{ width: `${this.props.miniWidth()}% `, height: `${this.props.miniHeight()}% `, left: `${this.props.miniLeft()}% `, top: `${this.props.miniTop()}% ` }} />;
+    }
+}
 @observer
 export class TabMinimapView extends React.Component<TabMinimapViewProps> {
     static miniStyleProvider = (doc: Opt<Doc>, props: Opt<DocumentViewProps>, property: string): any => {
@@ -513,25 +525,17 @@ export class TabMinimapView extends React.Component<TabMinimapViewProps> {
                     return 'none';
                 case StyleProp.DocContents:
                     const background = ((type: DocumentType) => {
+                        // prettier-ignore
                         switch (type) {
-                            case DocumentType.PDF:
-                                return 'pink';
-                            case DocumentType.AUDIO:
-                                return 'lightgreen';
-                            case DocumentType.WEB:
-                                return 'brown';
-                            case DocumentType.IMG:
-                                return 'blue';
-                            case DocumentType.MAP:
-                                return 'orange';
-                            case DocumentType.VID:
-                                return 'purple';
-                            case DocumentType.RTF:
-                                return 'yellow';
-                            case DocumentType.COL:
-                                return undefined;
-                            default:
-                                return 'gray';
+                            case DocumentType.PDF:    return 'pink';
+                            case DocumentType.AUDIO:  return 'lightgreen';
+                            case DocumentType.WEB:    return 'brown';
+                            case DocumentType.IMG:    return 'blue';
+                            case DocumentType.MAP:    return 'orange';
+                            case DocumentType.VID:    return 'purple';
+                            case DocumentType.RTF:    return 'yellow';
+                            case DocumentType.COL:    return undefined;
+                            default:                  return 'gray';
                         }
                     })(doc.type as DocumentType);
                     return !background ? undefined : <div style={{ width: doc[Width](), height: doc[Height](), position: 'absolute', display: 'block', background }} />;
@@ -551,13 +555,13 @@ export class TabMinimapView extends React.Component<TabMinimapViewProps> {
     returnMiniSize = () => NumCast(this.props.document._miniMapSize, 150);
     miniDown = (e: React.PointerEvent) => {
         const doc = this.props.document;
-        const renderBounds = this.renderBounds ?? { l: 0, r: 0, t: 0, b: 0, dim: 1 };
         const miniSize = this.returnMiniSize();
         doc &&
             setupMoveUpEvents(
                 this,
                 e,
                 action((e: PointerEvent, down: number[], delta: number[]) => {
+                    const renderBounds = this.renderBounds ?? { l: 0, r: 0, t: 0, b: 0, dim: 1 };
                     doc._freeform_panX = clamp(NumCast(doc._freeform_panX) + (delta[0] / miniSize) * renderBounds.dim, renderBounds.l, renderBounds.l + renderBounds.dim);
                     doc._freeform_panY = clamp(NumCast(doc._freeform_panY) + (delta[1] / miniSize) * renderBounds.dim, renderBounds.t, renderBounds.t + renderBounds.dim);
                     return false;
@@ -568,10 +572,11 @@ export class TabMinimapView extends React.Component<TabMinimapViewProps> {
     };
     popup = () => {
         if (!this.renderBounds) return <></>;
-        const miniWidth = (this.props.PanelWidth() / NumCast(this.props.document._freeform_scale, 1) / this.renderBounds.dim) * 100;
-        const miniHeight = (this.props.PanelHeight() / NumCast(this.props.document._freeform_scale, 1) / this.renderBounds.dim) * 100;
-        const miniLeft = 50 + ((NumCast(this.props.document._freeform_panX) - this.renderBounds.cx) / this.renderBounds.dim) * 100 - miniWidth / 2;
-        const miniTop = 50 + ((NumCast(this.props.document._freeform_panY) - this.renderBounds.cy) / this.renderBounds.dim) * 100 - miniHeight / 2;
+        const renderBounds = this.renderBounds;
+        const miniWidth = () => (this.props.PanelWidth() / NumCast(this.props.document._freeform_scale, 1) / renderBounds.dim) * 100;
+        const miniHeight = () => (this.props.PanelHeight() / NumCast(this.props.document._freeform_scale, 1) / renderBounds.dim) * 100;
+        const miniLeft = () => 50 + ((NumCast(this.props.document._freeform_panX) - renderBounds.cx) / renderBounds.dim) * 100 - miniWidth() / 2;
+        const miniTop = () => 50 + ((NumCast(this.props.document._freeform_panY) - renderBounds.cy) / renderBounds.dim) * 100 - miniHeight() / 2;
         const miniSize = this.returnMiniSize();
         return (
             <div className="miniMap" style={{ width: miniSize, height: miniSize, background: this.props.background() }}>
@@ -607,7 +612,7 @@ export class TabMinimapView extends React.Component<TabMinimapViewProps> {
                     fitContentsToBox={returnTrue}
                 />
                 <div className="miniOverlay" onPointerDown={this.miniDown}>
-                    <div className="miniThumb" style={{ width: `${miniWidth}% `, height: `${miniHeight}% `, left: `${miniLeft}% `, top: `${miniTop}% ` }} />
+                    <TabMiniThumb miniLeft={miniLeft} miniTop={miniTop} miniWidth={miniWidth} miniHeight={miniHeight} />
                 </div>
             </div>
         );
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 91669cf70..3a4719854 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -156,7 +156,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
             ? { x: cb[0], y: cb[1], r: cb[2], b: cb[3] }
             : this.props.contentBounds?.() ??
                   aggregateBounds(
-                      this._layoutElements.filter(e => e.bounds && e.bounds.width && !e.bounds.z).map(e => e.bounds!),
+                      this._layoutElements.filter(e => e.bounds?.width && !e.bounds.z).map(e => e.bounds!),
                       NumCast(this.layoutDoc._xPadding, 10),
                       NumCast(this.layoutDoc._yPadding, 10)
                   );
-- 
cgit v1.2.3-70-g09d2


From 9bff82f5d53f7d13802f8affc4759db0953d7dc7 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Tue, 19 Sep 2023 14:15:52 -0400
Subject: made goldenlayout tabs/buttons follow color scheme + added hover
 highlights. got rid of old color scheme code.

---
 src/client/goldenLayout.js                         |  14 +-
 src/client/util/CurrentUserUtils.ts                |  14 +-
 src/client/views/DocumentDecorations.tsx           |  10 +-
 src/client/views/MainView.scss                     |  90 +----
 src/client/views/MainView.tsx                      |   9 +-
 src/client/views/StyleProvider.tsx                 |  26 +-
 .../views/collections/CollectionDockingView.scss   | 396 +++++++++++++++++++--
 .../views/collections/CollectionDockingView.tsx    |  57 +--
 src/client/views/collections/TabDocView.tsx        |   1 +
 .../CollectionFreeFormLayoutEngines.tsx            |   2 +-
 .../views/nodes/formattedText/DashDocView.tsx      |   2 +-
 src/mobile/MobileInterface.tsx                     |   5 +-
 12 files changed, 448 insertions(+), 178 deletions(-)

(limited to 'src/client/views/collections/TabDocView.tsx')

diff --git a/src/client/goldenLayout.js b/src/client/goldenLayout.js
index 843b8bb5f..00ec5e439 100644
--- a/src/client/goldenLayout.js
+++ b/src/client/goldenLayout.js
@@ -1606,10 +1606,10 @@
             dragProxyHeight: 200
         },
         labels: {
-            close: 'close',
-            maximise: 'maximise',
+            close: 'close tab stack',
+            maximise: 'maximize stack',
             minimise: 'minimise',
-            popout: 'new tab',
+            popout: 'create new collection tab',
             popin: 'pop in',
             tabDropdown: 'additional tabs'
         }
@@ -2922,7 +2922,7 @@
      * @type {String}
      */
     lm.controls.Tab._template = '<li class="lm_tab"><i class="lm_left"></i>' +
-        '<div class="lm_title_wrap"><input class="lm_title"/></div><div class="lm_close_tab"></div>' +
+        '<div class="lm_title_wrap"><input class="lm_title"/></div><div class="lm_close_tab" title="close tab"></div>' +
         '<i class="lm_right"></i></li>';
 
     lm.utils.copy(lm.controls.Tab.prototype, {
@@ -5083,10 +5083,10 @@
             'column',
             'stack',
             'component',
-            'close',
-            'maximise',
+            'close tab stack',
+            'maximize stack',
             'minimise',
-            'new tab'
+            'create new collection tab'
         ];
     };
 
diff --git a/src/client/util/CurrentUserUtils.ts b/src/client/util/CurrentUserUtils.ts
index 452bb74cd..2983d778f 100644
--- a/src/client/util/CurrentUserUtils.ts
+++ b/src/client/util/CurrentUserUtils.ts
@@ -476,7 +476,6 @@ export class CurrentUserUtils {
     static setupDashboards(doc: Doc, field:string) {
         var myDashboards = DocCast(doc[field]);
 
-        const toggleDarkTheme = `this.colorScheme = this.colorScheme ? undefined : "${ColorScheme.Dark}"`;
         const newDashboard = `createNewDashboard()`;
 
         const reqdBtnOpts:DocumentOptions = { _forceActive: true,  _width: 30, _height: 30, _dragOnlyWithinContainer: true, _layout_hideContextMenu: true,
@@ -487,10 +486,10 @@ export class CurrentUserUtils {
         const contextMenuScripts = [/*newDashboard*/] as string[];
         const contextMenuLabels = [/*"Create New Dashboard"*/]  as string[];
         const contextMenuIcons = [/*"plus"*/]  as string[];
-        const childContextMenuScripts = [toggleDarkTheme, `toggleComicMode()`, `snapshotDashboard()`, `shareDashboard(self)`, 'removeDashboard(self)', 'resetDashboard(self)']; // entries must be kept in synch with childContextMenuLabels, childContextMenuIcons, and childContextMenuFilters
-        const childContextMenuFilters =  ['!IsNoviceMode()', '!IsNoviceMode()', '!IsNoviceMode()', undefined as any, undefined as any, '!IsNoviceMode()'];// entries must be kept in synch with childContextMenuLabels, childContextMenuIcons, and childContextMenuScripts
-        const childContextMenuLabels =  ["Toggle Dark Theme", "Toggle Comic Mode", "Snapshot Dashboard", "Share Dashboard", "Remove Dashboard", "Reset Dashboard"];// entries must be kept in synch with childContextMenuScripts, childContextMenuIcons, and childContextMenuFilters
-        const childContextMenuIcons = ["chalkboard", "tv", "camera", "users", "times", "trash"]; // entries must be kept in synch with childContextMenuScripts, childContextMenuLabels, and childContextMenuFilters
+        const childContextMenuScripts = [`toggleComicMode()`, `snapshotDashboard()`, `shareDashboard(self)`, 'removeDashboard(self)', 'resetDashboard(self)']; // entries must be kept in synch with childContextMenuLabels, childContextMenuIcons, and childContextMenuFilters
+        const childContextMenuFilters =  ['!IsNoviceMode()', '!IsNoviceMode()', undefined as any, undefined as any, '!IsNoviceMode()'];// entries must be kept in synch with childContextMenuLabels, childContextMenuIcons, and childContextMenuScripts
+        const childContextMenuLabels =  ["Toggle Comic Mode", "Snapshot Dashboard", "Share Dashboard", "Remove Dashboard", "Reset Dashboard"];// entries must be kept in synch with childContextMenuScripts, childContextMenuIcons, and childContextMenuFilters
+        const childContextMenuIcons = ["tv", "camera", "users", "times", "trash"]; // entries must be kept in synch with childContextMenuScripts, childContextMenuLabels, and childContextMenuFilters
         const reqdOpts:DocumentOptions = {
             title: "My Dashboards", childHideLinkButton: true, treeView_FreezeChildren: "remove|add", treeView_HideTitle: true, layout_boxShadow: "0 0", childDontRegisterViews: true,
             dropAction: "same", treeView_Type: TreeViewType.fileSystem, isFolder: true, isSystem: true,  treeView_TruncateTitleWidth: 350, ignoreClick: true, 
@@ -892,7 +891,6 @@ export class CurrentUserUtils {
         doc.defaultAclPrivate ?? (doc.defaultAclPrivate = false);
         doc.savedFilters ?? (doc.savedFilters = new List<Doc>());
         doc.userBackgroundColor ?? (doc.userBackgroundColor = Colors.DARK_GRAY);
-        addStyleSheetRule(SettingsManager._settingsStyle, 'lm_header', { background: `${doc.userBackgroundColor} !important` });
         doc.userVariantColor ?? (doc.userVariantColor = Colors.MEDIUM_BLUE);
         doc.userColor ?? (doc.userColor = Colors.LIGHT_GRAY);
         doc.userTheme ?? (doc.userTheme = ColorScheme.Dark);
@@ -920,10 +918,6 @@ export class CurrentUserUtils {
 
         Doc.GetProto(DocCast(Doc.UserDoc().emptyWebpage)).data = new WebField("https://www.wikipedia.org")
 
-        if (doc.activeDashboard instanceof Doc) {
-            // undefined means ColorScheme.Light until all CSS is updated with values for each color scheme (e.g., see MainView.scss, DocumentDecorations.scss)
-            doc.activeDashboard.colorScheme = doc.activeDashboard.colorScheme === ColorScheme.Light ? undefined : doc.activeDashboard.colorScheme;
-        }
         new LinkManager();
 
         DocServer.CacheNeedsUpdate && setTimeout(DocServer.UPDATE_SERVER_CACHE, 2500);
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 7e55b0ebc..327bb5585 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -804,8 +804,6 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P
             </Tooltip>
         );
 
-        const colorScheme = StrCast(Doc.ActiveDashboard?.colorScheme);
-
         const leftBounds = this.props.boundsLeft;
         const topBounds = LightboxView.LightboxDoc ? 0 : this.props.boundsTop;
         bounds.x = Math.max(leftBounds, bounds.x - this._resizeBorderWidth / 2) + this._resizeBorderWidth / 2;
@@ -818,7 +816,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P
         const useRotation = !hideResizers && seldocview.rootDoc.type !== DocumentType.EQUATION && seldocview.props.CollectionFreeFormDocumentView; // when do we want an object to not rotate?
         const rotation = SelectionManager.Views().length == 1 ? NumCast(seldocview.rootDoc._rotation) : 0;
 
-        const resizerScheme = colorScheme ? 'documentDecorations-resizer' + colorScheme : '';
+        const resizerScheme = '';
 
         // Radius constants
         const useRounding = seldocview.ComponentView instanceof ImageBox || seldocview.ComponentView instanceof FormattedTextBox || seldocview.ComponentView instanceof CollectionFreeFormView;
@@ -853,7 +851,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P
         const titleArea = this._editingTitle ? (
             <input
                 ref={this._keyinput}
-                className={`documentDecorations-title${colorScheme}`}
+                className="documentDecorations-title"
                 type="text"
                 name="dynbox"
                 autoComplete="on"
@@ -871,7 +869,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P
                     e.stopPropagation;
                 }}>
                 {hideTitle ? null : (
-                    <span className={`documentDecorations-titleSpan${colorScheme}`} onPointerDown={this.onTitleDown}>
+                    <span className="documentDecorations-titleSpan" onPointerDown={this.onTitleDown}>
                         {this.selectionTitle}
                     </span>
                 )}
@@ -887,7 +885,7 @@ export class DocumentDecorations extends React.Component<{ PanelWidth: number; P
         );
 
         return (
-            <div className={`documentDecorations${colorScheme}`} style={{ display: this._showNothing ? 'none' : undefined }}>
+            <div className="documentDecorations" style={{ display: this._showNothing ? 'none' : undefined }}>
                 <div
                     className="documentDecorations-background"
                     style={{
diff --git a/src/client/views/MainView.scss b/src/client/views/MainView.scss
index c880dde9a..98367969b 100644
--- a/src/client/views/MainView.scss
+++ b/src/client/views/MainView.scss
@@ -62,8 +62,7 @@ h1,
     pointer-events: none;
 }
 
-.mainView-container,
-.mainView-container-Dark {
+.mainView-container {
     width: 100%;
     height: 100%;
     position: absolute;
@@ -74,58 +73,12 @@ h1,
     touch-action: none;
 }
 
-.mainView-container,
-.mainView-container-Dark {
-    .lm_header .lm_tab {
-        padding: 0px;
-        //opacity: 0.7;
-        box-shadow: none;
-        height: 25px;
-        border-bottom: black solid;
-    }
-}
-
 .mainView-container {
     color: $dark-gray;
 
     .lm_goldenlayout {
         background: $medium-gray;
     }
-
-    .lm_title {
-        background: $light-gray;
-        color: $dark-gray;
-    }
-}
-
-.mainView-container-Dark {
-    color: $light-gray;
-
-    .lm_goldenlayout {
-        background: $medium-gray;
-    }
-
-    .lm_title {
-        background: $dark-gray;
-        color: unset;
-    }
-
-    .marquee {
-        border-color: $white;
-    }
-
-    #search-input {
-        background: $light-gray;
-    }
-
-    .contextMenu-cont,
-    .contextMenu-item {
-        background: $dark-gray;
-    }
-
-    .contextMenu-item:hover {
-        background: $medium-gray;
-    }
 }
 
 .mainView-dashboardArea {
@@ -172,8 +125,7 @@ h1,
     }
 }
 
-.mainView-innerContent,
-.mainView-innerContent-Dark {
+.mainView-innerContent {
     display: contents;
     flex-direction: row;
     position: relative;
@@ -206,44 +158,6 @@ h1,
     background-color: $light-gray;
 }
 
-.mainView-innerContent-Dark {
-    .propertiesView {
-        background-color: #252525;
-
-        input {
-            background-color: $medium-gray;
-        }
-
-        .propertiesView-sharingTable {
-            background-color: $medium-gray;
-        }
-
-        .editable-title {
-            background-color: $medium-gray;
-        }
-
-        .propertiesView-field {
-            background-color: $medium-gray;
-        }
-    }
-
-    .mainView-propertiesDragger,
-    .mainView-libraryHandle {
-        background: #353535;
-    }
-}
-
-.mainView-container-Dark {
-    .contextMenu-cont {
-        background: $medium-gray;
-        color: $white;
-
-        input::placeholder {
-            color: $white;
-        }
-    }
-}
-
 .mainView-leftMenuPanel {
     min-width: var(--menuPanelWidth);
     border-right: $standard-border;
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 707cf3a34..6d08c01fa 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -112,9 +112,6 @@ export class MainView extends React.Component {
     @computed private get userDoc() {
         return Doc.UserDoc();
     }
-    @computed private get colorScheme() {
-        return StrCast(Doc.ActiveDashboard?.colorScheme);
-    }
     @observable mainDoc: Opt<Doc>;
     @computed private get mainContainer() {
         if (window.location.pathname.startsWith('/doc/') && Doc.CurrentUserEmail === 'guest') {
@@ -800,7 +797,7 @@ export class MainView extends React.Component {
         return (
             <>
                 {this._hideUI ? null : this.leftMenuPanel}
-                <div key="inner" className={`mainView-innerContent${this.colorScheme}`}>
+                <div key="inner" className="mainView-innerContent">
                     {this.flyout}
                     <div
                         className="mainView-libraryHandle"
@@ -843,7 +840,7 @@ export class MainView extends React.Component {
                         ).observe(r);
                 }}
                 style={{
-                    color: this.colorScheme === ColorScheme.Dark ? 'rgb(205,205,205)' : 'black',
+                    color: 'black',
                     height: `calc(100% - ${this.topOfDashUI + this.topMenuHeight()}px)`,
                     width: '100%',
                 }}>
@@ -1003,7 +1000,7 @@ export class MainView extends React.Component {
     render() {
         return (
             <div
-                className={`mainView-container ${this.colorScheme}`}
+                className="mainView-container"
                 style={{
                     color: SettingsManager.userColor,
                     background: SettingsManager.userBackgroundColor,
diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx
index 1a4b8d7d2..d7537bffb 100644
--- a/src/client/views/StyleProvider.tsx
+++ b/src/client/views/StyleProvider.tsx
@@ -52,10 +52,6 @@ export enum StyleProp {
     Highlighting = 'highlighting', // border highlighting
 }
 
-function darkScheme() {
-    return Doc.ActiveDashboard?.colorScheme === ColorScheme.Dark;
-}
-
 function toggleLockedPosition(doc: Doc) {
     UndoManager.RunInBatch(
         () =>
@@ -135,7 +131,7 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps
             }
             return undefined;
         case StyleProp.DocContents:return undefined;
-        case StyleProp.WidgetColor:return isAnnotated ? Colors.LIGHT_BLUE : darkScheme() ? 'lightgrey' : 'dimgrey';
+        case StyleProp.WidgetColor:return isAnnotated ? Colors.LIGHT_BLUE : 'dimgrey';
         case StyleProp.Opacity:    return props?.LayoutTemplateString?.includes(KeyValueBox.name) ? 1 : doc?.text_inlineAnnotations ? 0 :  Cast(doc?._opacity, "number", Cast(doc?.opacity, 'number', null));
         case StyleProp.HideLinkBtn:return props?.hideLinkButton || (!selected && doc?.layout_hideLinkButton);
         case StyleProp.FontSize:   return StrCast(doc?.[fieldKey + 'fontSize'],   StrCast(doc?._text_fontSize,   StrCast(Doc.UserDoc().fontSize)));
@@ -203,21 +199,21 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps
             // prettier-ignore
             switch (doc?.type) {
                 case DocumentType.SLIDER:      break;
-                case DocumentType.PRESELEMENT: docColor = docColor || (darkScheme() ? '' : ''); break;
-                case DocumentType.PRES:        docColor = docColor || (darkScheme() ? 'transparent' : 'transparent'); break;
+                case DocumentType.PRESELEMENT: docColor = docColor || ""; break;
+                case DocumentType.PRES:        docColor = docColor || 'transparent'; break;
                 case DocumentType.FONTICON:    docColor = boxBackground ? undefined : docColor || Colors.DARK_GRAY; break;
-                case DocumentType.RTF:         docColor = docColor || (darkScheme() ? Colors.DARK_GRAY : Colors.LIGHT_GRAY); break;
+                case DocumentType.RTF:         docColor = docColor ||  Colors.LIGHT_GRAY; break;
                 case DocumentType.INK:         docColor = doc?.stroke_isInkMask ? 'rgba(0,0,0,0.7)' : undefined; break;
                 case DocumentType.EQUATION:    docColor = docColor || 'transparent'; break;
-                case DocumentType.LABEL:       docColor = docColor || (darkScheme() ? Colors.DARK_GRAY : Colors.LIGHT_GRAY); break;
-                case DocumentType.BUTTON:      docColor = docColor || (darkScheme() ? Colors.DARK_GRAY : Colors.LIGHT_GRAY); break;
+                case DocumentType.LABEL:       docColor = docColor || Colors.LIGHT_GRAY; break;
+                case DocumentType.BUTTON:      docColor = docColor ||  Colors.LIGHT_GRAY; break;
                 case DocumentType.LINK:        docColor = (isAnchor ? docColor : '') || 'transparent'; break;
                 case DocumentType.IMG:
                 case DocumentType.WEB:
                 case DocumentType.PDF:
                 case DocumentType.MAP:
                 case DocumentType.SCREENSHOT:
-                case DocumentType.VID:         docColor = docColor || (darkScheme() ? Colors.DARK_GRAY : Colors.LIGHT_GRAY); break;
+                case DocumentType.VID:         docColor = docColor || (Colors.LIGHT_GRAY); break;
                 case DocumentType.COL:
                     if (StrCast(Doc.LayoutField(doc)).includes(SliderBox.name)) break;
                     docColor = docColor || (Doc.IsSystem(doc)
@@ -227,11 +223,11 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps
                             : doc?._isGroup
                             ? undefined
                             : doc._type_collection === CollectionViewType.Stacking ?
-                            (darkScheme() ? Colors.MEDIUM_GRAY : Colors.DARK_GRAY)
-                            : Cast((props?.renderDepth || 0) > 0 ? Doc.UserDoc().activeCollectionNestedBackground : Doc.UserDoc().activeCollectionBackground, 'string') ?? (darkScheme() ? Colors.BLACK : Colors.MEDIUM_GRAY));
+                            (Colors.DARK_GRAY)
+                            : Cast((props?.renderDepth || 0) > 0 ? Doc.UserDoc().activeCollectionNestedBackground : Doc.UserDoc().activeCollectionBackground, 'string') ?? (Colors.MEDIUM_GRAY));
                     break;
                 //if (doc._type_collection !== CollectionViewType.Freeform && doc._type_collection !== CollectionViewType.Time) return "rgb(62,62,62)";
-                default: docColor = docColor || (darkScheme() ? Colors.DARK_GRAY : Colors.WHITE);
+                default: docColor = docColor || (Colors.WHITE);
             }
             return (docColor && !doc) ? DashColor(docColor).fade(0.5).toString() : docColor;
         }
@@ -247,7 +243,7 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<DocumentViewProps
                             ? '4px 4px 10px 2px'
                             : lockedPosition() || doc?._isGroup || docProps?.LayoutTemplateString
                             ? undefined // groups have no drop shadow -- they're supposed to be "invisible".  LayoutString's imply collection is being rendered as something else (e.g., title of a Slide)
-                            : `${darkScheme() ? Colors.DARK_GRAY : Colors.MEDIUM_GRAY} ${StrCast(doc.layout_boxShadow, '0.2vw 0.2vw 0.8vw')}`
+                            : `${Colors.MEDIUM_GRAY} ${StrCast(doc.layout_boxShadow, '0.2vw 0.2vw 0.8vw')}`
                     );
 
                 case DocumentType.LABEL:
diff --git a/src/client/views/collections/CollectionDockingView.scss b/src/client/views/collections/CollectionDockingView.scss
index b13753025..132250bae 100644
--- a/src/client/views/collections/CollectionDockingView.scss
+++ b/src/client/views/collections/CollectionDockingView.scss
@@ -1,5 +1,284 @@
 @import '../global/globalCssVariables.scss';
-@import '../../../../node_modules/golden-layout/src/css/goldenlayout-base.css';
+
+.lm_root {
+    position: relative;
+}
+.lm_row > .lm_item {
+    float: left;
+}
+.lm_content {
+    overflow: hidden;
+    position: relative;
+}
+.lm_dragging,
+.lm_dragging * {
+    cursor: move !important;
+    user-select: none;
+}
+.lm_maximised {
+    position: absolute;
+    top: 0;
+    left: 0;
+    z-index: 40;
+}
+.lm_maximise_placeholder {
+    display: none;
+}
+.lm_splitter {
+    position: relative;
+    z-index: 20;
+}
+.lm_splitter:hover,
+.lm_splitter.lm_dragging {
+    background: orange;
+}
+.lm_splitter.lm_vertical .lm_drag_handle {
+    width: 100%;
+    position: absolute;
+    cursor: ns-resize;
+}
+.lm_splitter.lm_horizontal {
+    float: left;
+    height: 100%;
+}
+.lm_splitter.lm_horizontal .lm_drag_handle {
+    height: 100%;
+    position: absolute;
+    cursor: ew-resize;
+}
+.lm_header {
+    overflow: visible;
+    position: relative;
+    z-index: 1;
+}
+// .lm_header [class^='lm_'] {
+//     box-sizing: content-box !important;
+// }
+.lm_header .lm_controls {
+    position: absolute;
+    right: 3px;
+}
+.lm_header .lm_controls > li {
+    cursor: pointer;
+    float: left;
+    width: 18px;
+    height: 18px;
+    text-align: center;
+}
+.lm_header ul {
+    margin: 0;
+    padding: 0;
+    list-style-type: none;
+}
+.lm_header .lm_tabs {
+    position: absolute;
+}
+.lm_header .lm_tab {
+    cursor: pointer;
+    float: left;
+    height: 25px;
+    padding: 0 10px 5px;
+    padding-right: 25px;
+    position: relative;
+    box-shadow: unset !important;
+}
+.lm_header .lm_tab i {
+    width: 2px;
+    height: 19px;
+    position: absolute;
+}
+.lm_header .lm_tab i.lm_left {
+    top: 0;
+    left: -2px;
+}
+.lm_header .lm_tab i.lm_right {
+    top: 0;
+    right: -2px;
+}
+.lm_header .lm_tab .lm_title {
+    display: inline-block;
+    overflow: hidden;
+    text-overflow: ellipsis;
+}
+.lm_header .lm_tab .lm_close_tab {
+    width: 14px;
+    height: 14px;
+    position: absolute;
+    top: 0;
+    right: 0;
+    text-align: center;
+}
+.lm_stack.lm_left .lm_header,
+.lm_stack.lm_right .lm_header {
+    height: 100%;
+}
+.lm_dragProxy.lm_left .lm_header,
+.lm_dragProxy.lm_right .lm_header,
+.lm_stack.lm_left .lm_header,
+.lm_stack.lm_right .lm_header {
+    width: 20px;
+    float: left;
+    vertical-align: top;
+}
+.lm_dragProxy.lm_left .lm_header .lm_tabs,
+.lm_dragProxy.lm_right .lm_header .lm_tabs,
+.lm_stack.lm_left .lm_header .lm_tabs,
+.lm_stack.lm_right .lm_header .lm_tabs {
+    transform-origin: left top;
+    top: 0;
+    width: 1000px;
+}
+.lm_dragProxy.lm_left .lm_header .lm_controls,
+.lm_dragProxy.lm_right .lm_header .lm_controls,
+.lm_stack.lm_left .lm_header .lm_controls,
+.lm_stack.lm_right .lm_header .lm_controls {
+    bottom: 0;
+}
+.lm_dragProxy.lm_left .lm_items,
+.lm_dragProxy.lm_right .lm_items,
+.lm_stack.lm_left .lm_items,
+.lm_stack.lm_right .lm_items {
+    float: left;
+}
+.lm_dragProxy.lm_left .lm_header .lm_tabs,
+.lm_stack.lm_left .lm_header .lm_tabs {
+    transform: rotate(-90deg) scaleX(-1);
+    left: 0;
+}
+.lm_dragProxy.lm_left .lm_header .lm_tabs .lm_tab,
+.lm_stack.lm_left .lm_header .lm_tabs .lm_tab {
+    transform: scaleX(-1);
+    margin-top: 1px;
+}
+.lm_dragProxy.lm_left .lm_header .lm_tabdropdown_list,
+.lm_stack.lm_left .lm_header .lm_tabdropdown_list {
+    top: initial;
+    right: initial;
+    left: 20px;
+}
+.lm_dragProxy.lm_right .lm_content {
+    float: left;
+}
+.lm_dragProxy.lm_right .lm_header .lm_tabs,
+.lm_stack.lm_right .lm_header .lm_tabs {
+    transform: rotate(90deg) scaleX(1);
+    left: 100%;
+    margin-left: 0;
+}
+.lm_dragProxy.lm_right .lm_header .lm_controls,
+.lm_stack.lm_right .lm_header .lm_controls {
+    left: 3px;
+}
+.lm_dragProxy.lm_right .lm_header .lm_tabdropdown_list,
+.lm_stack.lm_right .lm_header .lm_tabdropdown_list {
+    top: initial;
+    right: 20px;
+}
+.lm_dragProxy.lm_bottom .lm_header .lm_tab,
+.lm_stack.lm_bottom .lm_header .lm_tab {
+    margin-top: 0;
+    border-top: none;
+}
+.lm_dragProxy.lm_bottom .lm_header .lm_controls,
+.lm_stack.lm_bottom .lm_header .lm_controls {
+    top: 3px;
+}
+.lm_dragProxy.lm_bottom .lm_header .lm_tabdropdown_list,
+.lm_stack.lm_bottom .lm_header .lm_tabdropdown_list {
+    top: initial;
+    bottom: 20px;
+}
+.lm_drop_tab_placeholder {
+    float: left;
+    width: 100px;
+    height: 10px;
+    visibility: hidden;
+}
+.lm_header .lm_controls .lm_tabdropdown:before {
+    content: '';
+    width: 0;
+    height: 0;
+    vertical-align: middle;
+    display: inline-block;
+    border-top: 5px dashed;
+    border-right: 5px solid transparent;
+    border-left: 5px solid transparent;
+    color: white;
+}
+.lm_header .lm_tabdropdown_list {
+    position: absolute;
+    top: 20px;
+    right: 0;
+    z-index: 5;
+    overflow: hidden;
+}
+.lm_header .lm_tabdropdown_list .lm_tab {
+    clear: both;
+    padding-right: 10px;
+    margin: 0;
+}
+.lm_header .lm_tabdropdown_list .lm_tab .lm_title {
+    width: 100px;
+}
+.lm_header .lm_tabdropdown_list .lm_close_tab {
+    display: none !important;
+}
+.lm_dragProxy {
+    position: absolute;
+    top: 0;
+    left: 0;
+    z-index: 30;
+}
+.lm_dragProxy .lm_header {
+    background: transparent;
+}
+.lm_dragProxy .lm_content {
+    border-top: none;
+    overflow: hidden;
+}
+.lm_dropTargetIndicator {
+    display: none;
+    position: absolute;
+    z-index: 20;
+}
+.lm_dropTargetIndicator .lm_inner {
+    width: 100%;
+    height: 100%;
+    position: relative;
+    top: 0;
+    left: 0;
+}
+.lm_transition_indicator {
+    display: none;
+    width: 20px;
+    height: 20px;
+    position: absolute;
+    top: 0;
+    left: 0;
+    z-index: 20;
+}
+.lm_popin {
+    width: 20px;
+    height: 20px;
+    position: absolute;
+    bottom: 0;
+    right: 0;
+    z-index: 9999;
+}
+.lm_popin > * {
+    width: 100%;
+    height: 100%;
+    position: absolute;
+    top: 0;
+    left: 0;
+}
+.lm_popin > .lm_bg {
+    z-index: 10;
+}
+.lm_popin > .lm_icon {
+    z-index: 20;
+} /*# sourceMappingURL=goldenlayout-base.css.map */
+
 @import '../../../../node_modules/golden-layout/src/css/goldenlayout-dark-theme.css';
 
 .lm_title {
@@ -46,18 +325,33 @@
     // font-weight: 700;
 }
 
+.lm_header .lm_tabs {
+    overflow-y: hidden;
+    width: 100%;
+}
+ul.lm_tabs::before {
+    content: ' ';
+    position: absolute;
+    bottom: 0;
+    width: 100%;
+    z-index: 1;
+    pointer-events: none;
+    border: solid 1px black;
+}
 .lm_header .lm_tab {
     // padding: 0px;  // moved to MainView.scss, othwerise they get overridden by default stylings
     // opacity: 0.7;
     // box-shadow: none;
     // height: 25px;
     // border-bottom: black solid;
+    border-bottom: unset !important;
+    border-top-right-radius: 5px;
+    border-top-left-radius: 5px;
 
     .collectionDockingView-gear {
         display: none;
     }
 }
-
 .lm_header .lm_tab.lm_active {
     padding: 0;
     opacity: 1;
@@ -65,7 +359,11 @@
     box-shadow: none;
     height: 27px;
     margin-right: 2px;
-    // border-bottom: unset;
+    z-index: 2 !important;
+    border-right: solid 2px;
+    border-left: solid 2px;
+    border-top: solid 2px;
+    border-color: black;
 
     .collectionDockingView-gear {
         display: inline-block;
@@ -123,20 +421,63 @@
 }
 
 .lm_close_tab {
+    display: inline-flex !important;
+    opacity: 0 !important;
     padding: 0;
     align-self: center;
     margin-right: 5px;
-    background-color: black;
     border-radius: 3px;
-    opacity: 1 !important;
     width: 15px !important;
     height: 15px !important;
     position: relative !important;
-    display: inline-flex !important;
     align-items: center;
     top: 0 !important;
     right: unset !important;
     left: 0 !important;
+    background-image: unset !important;
+    &::before {
+        content: 'x';
+        color: rgb(50, 50, 50);
+        margin: auto;
+        position: relative;
+        top: -2px;
+    }
+    &:hover {
+        display: inline-flex !important;
+        &::before {
+            color: white;
+        }
+    }
+}
+.lm_close {
+    background-image: unset !important;
+    &:hover {
+        background: gray;
+        color: white !important;
+    }
+    &::before {
+        content: 'x';
+        margin: auto;
+        position: relative;
+        top: -2;
+        font-size: medium;
+        font-family: sans-serif;
+    }
+}
+.lm_active .lm_close_tab {
+    opacity: 1 !important;
+}
+.lm_tab:hover {
+    .lm_close_tab {
+        opacity: 1 !important;
+    }
+}
+
+.lm_iconWrap {
+    &:hover {
+        background: gray;
+        color: white !important;
+    }
 }
 
 .lm_tab,
@@ -154,14 +495,6 @@
     top: 0;
     left: 0;
 
-    // overflow: hidden;  // bcz: menus don't show up when this is on (e.g., the parentSelectorMenu)
-    .collectionDockingView-gear {
-        padding-left: 5px;
-        height: 15px;
-        width: 18px;
-        margin: auto;
-    }
-
     .collectionDockingView-drag {
         touch-action: none;
         position: absolute;
@@ -180,7 +513,6 @@
         display: flex;
         align-content: center;
         justify-content: center;
-        background: $dark-gray;
     }
 
     .lm_controls > li {
@@ -190,14 +522,38 @@
     }
 
     .lm_controls .lm_popout {
-        transform: rotate(45deg);
-        background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAYAAADgkQYQAAAAQUlEQVR4nHXOQQ4AMAgCQeT/f6aXpsGK3jSTuCVJAAr7iBdoAwCKd0nwfaAdHbYERw5b44+E8JoBjEYGMBq5gAYP3usUDu2IvoUAAAAASUVORK5CYII=);
+        background-image: unset;
+        left: -3;
+        &:hover {
+            background: gray;
+            color: white !important;
+        }
+    }
+    li.lm_popout::before {
+        content: '+';
+        margin: auto;
+        font-size: x-large;
+        top: -8;
+        position: relative;
+    }
+    .lm_maximise {
+        background-image: unset !important;
+        &::before {
+            content: '\25A3';
+            margin: auto;
+            font-size: medium;
+            position: relative;
+        }
+        &:hover {
+            background: gray;
+            color: white !important;
+        }
     }
 
     .lm_maximised .lm_controls .lm_maximise {
-        opacity: 1;
-        transform: scale(0.8);
-        background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAJCAYAAADgkQYQAAAAKElEQVR4nGP8////fwYCgImQAgYGBgYWKM2IR81/okwajIpgvsMbVgAwgQYRVakEKQAAAABJRU5ErkJggg==) !important;
+        &::before {
+            content: '\25A2';
+        }
     }
 
     .flexlayout__layout {
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index 8472c59db..4873a61ff 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -10,7 +10,7 @@ import { List } from '../../../fields/List';
 import { ImageCast, NumCast, StrCast } from '../../../fields/Types';
 import { ImageField } from '../../../fields/URLField';
 import { GetEffectiveAcl, inheritParentAcls } from '../../../fields/util';
-import { emptyFunction, incrementTitleCopy } from '../../../Utils';
+import { addStyleSheet, addStyleSheetRule, clearStyleSheetRules, emptyFunction, incrementTitleCopy } from '../../../Utils';
 import { DocServer } from '../../DocServer';
 import { Docs } from '../../documents/Documents';
 import { CollectionViewType, DocumentType } from '../../documents/DocumentTypes';
@@ -31,6 +31,7 @@ import { CollectionFreeFormView } from './collectionFreeForm';
 import { CollectionSubView, SubCollectionViewProps } from './CollectionSubView';
 import { TabDocView } from './TabDocView';
 import React = require('react');
+import { SettingsManager } from '../../util/SettingsManager';
 const _global = (window /* browser */ || global) /* node */ as any;
 
 @observer
@@ -60,7 +61,7 @@ export class CollectionDockingView extends CollectionSubView() {
         return this._goldenLayout._maximisedItem !== null;
     }
     private _goldenLayout: any = null;
-
+    static _highlightStyleSheet: any = addStyleSheet();
     constructor(props: SubCollectionViewProps) {
         super(props);
         if (this.props.renderDepth < 0) runInAction(() => (CollectionDockingView.Instance = this));
@@ -330,6 +331,16 @@ export class CollectionDockingView extends CollectionSubView() {
                 width => !this._goldenLayout && width > 20 && setTimeout(() => this.setupGoldenLayout()), // need to wait for the collectiondockingview-container to have it's width/height since golden layout reads that to configure its windows
                 { fireImmediately: true }
             );
+            reaction(
+                () => [SettingsManager.userBackgroundColor, SettingsManager.userBackgroundColor],
+                () => {
+                    clearStyleSheetRules(CollectionDockingView._highlightStyleSheet);
+                    addStyleSheetRule(CollectionDockingView._highlightStyleSheet, 'lm_controls', { background: `${SettingsManager.userBackgroundColor} !important` });
+                    addStyleSheetRule(CollectionDockingView._highlightStyleSheet, 'lm_controls', { color: `${SettingsManager.userColor} !important` });
+                    addStyleSheetRule(SettingsManager._settingsStyle, 'lm_header', { background: `${SettingsManager.userBackgroundColor} !important` });
+                },
+                { fireImmediately: true }
+            );
         }
     };
 
@@ -505,6 +516,23 @@ export class CollectionDockingView extends CollectionSubView() {
             }
         });
 
+        let addNewDoc = action(() => {
+            const dashboard = Doc.ActiveDashboard;
+            if (dashboard) {
+                dashboard['pane-count'] = NumCast(dashboard['pane-count']) + 1;
+                const docToAdd = Docs.Create.FreeformDocument([], {
+                    _width: this.props.PanelWidth(),
+                    _height: this.props.PanelHeight(),
+                    _layout_fitWidth: true,
+                    _freeform_backgroundGrid: true,
+                    title: `Untitled Tab ${NumCast(dashboard['pane-count'])}`,
+                });
+                Doc.AddDocToList(Doc.MyHeaderBar, 'data', docToAdd);
+                inheritParentAcls(this.dataDoc, docToAdd, false);
+                CollectionDockingView.AddSplit(docToAdd, OpenWhereMod.none, stack);
+            }
+        });
+
         stack.header?.controlsContainer
             .find('.lm_close') //get the close icon
             .off('click') //unbind the current click handler
@@ -524,31 +552,18 @@ export class CollectionDockingView extends CollectionSubView() {
                 })
             );
 
+        stack.element.click((e: any) => {
+            if (stack.contentItems.length === 0 && Array.from(document.elementsFromPoint(e.originalEvent.x, e.originalEvent.y)).some(ele => ele?.className === 'empty-tabs-message')) {
+                addNewDoc();
+            }
+        });
         stack.header?.controlsContainer
             .find('.lm_maximise') //get the close icon
             .click(() => setTimeout(this.stateChanged));
         stack.header?.controlsContainer
             .find('.lm_popout') //get the popout icon
             .off('click') //unbind the current click handler
-            .click(
-                action(() => {
-                    // stack.config.fixed = !stack.config.fixed;  // force the stack to have a fixed size
-                    const dashboard = Doc.ActiveDashboard;
-                    if (dashboard) {
-                        dashboard['pane-count'] = NumCast(dashboard['pane-count']) + 1;
-                        const docToAdd = Docs.Create.FreeformDocument([], {
-                            _width: this.props.PanelWidth(),
-                            _height: this.props.PanelHeight(),
-                            _layout_fitWidth: true,
-                            _freeform_backgroundGrid: true,
-                            title: `Untitled Tab ${NumCast(dashboard['pane-count'])}`,
-                        });
-                        Doc.AddDocToList(Doc.MyHeaderBar, 'data', docToAdd);
-                        inheritParentAcls(this.dataDoc, docToAdd, false);
-                        CollectionDockingView.AddSplit(docToAdd, OpenWhereMod.none, stack);
-                    }
-                })
-            );
+            .click(addNewDoc);
     };
 
     render() {
diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx
index dab53b671..26aa5a121 100644
--- a/src/client/views/collections/TabDocView.tsx
+++ b/src/client/views/collections/TabDocView.tsx
@@ -132,6 +132,7 @@ export class TabDocView extends React.Component<TabDocViewProps> {
 
             if (tab.element[0].children[1].children.length === 1) {
                 iconWrap.className = 'lm_iconWrap lm_moreInfo';
+                iconWrap.title = 'click for menu, drag to embed in document';
                 const dragBtnDown = (e: React.PointerEvent) => {
                     setupMoveUpEvents(
                         this,
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx
index 1e76d373c..15b6e1d37 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormLayoutEngines.tsx
@@ -350,7 +350,7 @@ export function computeTimelineLayout(poolData: Map<string, PoolData>, pivotDoc:
         groupNames.push({ type: 'text', text: toLabel(Math.ceil(maxTime)), x: Math.ceil(maxTime - minTime) * scaling, y: 0, height: fontHeight, fontSize, payload: undefined });
     }
 
-    const divider = { type: 'div', color: Doc.ActiveDashboard?.colorScheme === ColorScheme.Dark ? 'dimgray' : 'black', x: 0, y: 0, width: panelDim[0], height: -1, payload: undefined };
+    const divider = { type: 'div', color: 'black', x: 0, y: 0, width: panelDim[0], height: -1, payload: undefined };
     return normalizeResults(panelDim, fontHeight, docMap, poolData, viewDefsToJSX, groupNames, (maxTime - minTime) * scaling, [divider]);
 
     function layoutDocsAtTime(keyDocs: Doc[], key: number) {
diff --git a/src/client/views/nodes/formattedText/DashDocView.tsx b/src/client/views/nodes/formattedText/DashDocView.tsx
index 48f4c2afd..5349e6966 100644
--- a/src/client/views/nodes/formattedText/DashDocView.tsx
+++ b/src/client/views/nodes/formattedText/DashDocView.tsx
@@ -22,7 +22,7 @@ export class DashDocView {
         this.dom = document.createElement('span');
         this.dom.style.position = 'relative';
         this.dom.style.textIndent = '0';
-        this.dom.style.border = '1px solid ' + StrCast(tbox.layoutDoc.color, Doc.ActiveDashboard?.colorScheme === ColorScheme.Dark ? 'dimgray' : 'lightGray');
+        this.dom.style.border = '1px solid ' + StrCast(tbox.layoutDoc.color, 'lightGray');
         this.dom.style.width = node.attrs.width;
         this.dom.style.height = node.attrs.height;
         this.dom.style.display = node.attrs.hidden ? 'none' : 'inline-block';
diff --git a/src/mobile/MobileInterface.tsx b/src/mobile/MobileInterface.tsx
index c16a1c124..498bec6ed 100644
--- a/src/mobile/MobileInterface.tsx
+++ b/src/mobile/MobileInterface.tsx
@@ -588,11 +588,10 @@ export class MobileInterface extends React.Component {
         const freeformDoc = Doc.GuestTarget || Docs.Create.FreeformDocument([], freeformOptions);
         const dashboardDoc = Docs.Create.StandardCollectionDockingDocument([{ doc: freeformDoc, initialWidth: 600 }], { title: `Dashboard ${dashboardCount}` }, id, 'row');
 
-        const toggleTheme = ScriptField.MakeScript(`self.colorScheme = self.colorScheme ? undefined: ${ColorScheme.Dark}}`);
         const toggleComic = ScriptField.MakeScript(`toggleComicMode()`);
         const cloneDashboard = ScriptField.MakeScript(`cloneDashboard()`);
-        dashboardDoc.contextMenuScripts = new List<ScriptField>([toggleTheme!, toggleComic!, cloneDashboard!]);
-        dashboardDoc.contextMenuLabels = new List<string>(['Toggle Theme Colors', 'Toggle Comic Mode', 'New Dashboard Layout']);
+        dashboardDoc.contextMenuScripts = new List<ScriptField>([toggleComic!, cloneDashboard!]);
+        dashboardDoc.contextMenuLabels = new List<string>(['Toggle Comic Mode', 'New Dashboard Layout']);
 
         Doc.AddDocToList(scens, 'data', dashboardDoc);
     };
-- 
cgit v1.2.3-70-g09d2

