aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/MainView.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views/MainView.tsx')
-rw-r--r--src/client/views/MainView.tsx179
1 files changed, 117 insertions, 62 deletions
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 84c1037dd..e51aee40c 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -8,11 +8,9 @@ import { observer } from 'mobx-react';
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { Doc, DocListCast, Opt } from '../../fields/Doc';
-import { List } from '../../fields/List';
import { PrefetchProxy } from '../../fields/Proxy';
import { ScriptField } from '../../fields/ScriptField';
import { PromiseValue, StrCast } from '../../fields/Types';
-import { TraceMobx } from '../../fields/util';
import { emptyFunction, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue, returnZero, setupMoveUpEvents, simulateMouseClick, Utils } from '../../Utils';
import { GoogleAuthenticationManager } from '../apis/GoogleAuthenticationManager';
import { DocServer } from '../DocServer';
@@ -34,7 +32,8 @@ import { CollectionDockingView } from './collections/CollectionDockingView';
import { MarqueeOptionsMenu } from './collections/collectionFreeForm/MarqueeOptionsMenu';
import { CollectionLinearView } from './collections/collectionLinear';
import { CollectionMenu } from './collections/CollectionMenu';
-import { CollectionViewType } from './collections/CollectionView';
+import { TreeViewType } from './collections/CollectionTreeView';
+import { CollectionView, CollectionViewType } from './collections/CollectionView';
import "./collections/TreeView.scss";
import { ComponentDecorations } from './ComponentDecorations';
import { ContextMenu } from './ContextMenu';
@@ -52,6 +51,7 @@ import { AudioBox } from './nodes/AudioBox';
import { ButtonType } from './nodes/button/FontIconBox';
import { DocumentLinksButton } from './nodes/DocumentLinksButton';
import { DocumentView } from './nodes/DocumentView';
+import { DashFieldViewMenu } from './nodes/formattedText/DashFieldView';
import { FormattedTextBox } from './nodes/formattedText/FormattedTextBox';
import { RichTextMenu } from './nodes/formattedText/RichTextMenu';
import { LinkDescriptionPopup } from './nodes/LinkDescriptionPopup';
@@ -83,14 +83,19 @@ export class MainView extends React.Component {
@computed private get dashboardTabHeight() { return 27; } // 27 comes form lm.config.defaultConfig.dimensions.headerHeight in goldenlayout.js
@computed private get topOfDashUI() { return Number(DASHBOARD_SELECTOR_HEIGHT.replace("px", "")); }
- @computed private get topOfMainDoc() { return this.topOfDashUI + this.topMenuHeight(); }
+ @computed private get topOfHeaderBarDoc() { return this.topOfDashUI + this.topMenuHeight(); }
+ @computed private get topOfSidebarDoc() { return this.topOfDashUI + this.topMenuHeight(); }
+ @computed private get topOfMainDoc() { return this.topOfDashUI + this.topMenuHeight() + this.headerBarDocHeight(); }
@computed private get topOfMainDocContent() { return this.topOfMainDoc + this.dashboardTabHeight; }
@computed private get leftScreenOffsetOfMainDocView() { return this.leftMenuWidth() - 2; }
@computed private get userDoc() { return Doc.UserDoc(); }
@computed private get colorScheme() { return StrCast(CurrentUserUtils.ActiveDashboard?.colorScheme); }
@computed private get mainContainer() { return this.userDoc ? CurrentUserUtils.ActiveDashboard : CurrentUserUtils.GuestDashboard; }
+ @computed private get headerBarDoc() { return this.userDoc ? CurrentUserUtils.MyHeaderBarDoc : CurrentUserUtils.MyHeaderBarDoc; }
@computed public get mainFreeform(): Opt<Doc> { return (docs => (docs?.length > 1) ? docs[1] : undefined)(DocListCast(this.mainContainer!.data)); }
+ headerBarDocWidth = () => this.mainDocViewWidth();
+ headerBarDocHeight = () => CurrentUserUtils.headerBarHeight ?? 0;
topMenuHeight = () => 35;
topMenuWidth = returnZero; // value is ignored ...
leftMenuWidth = () => Number(LEFT_MENU_WIDTH.replace("px", ""));
@@ -99,8 +104,8 @@ export class MainView extends React.Component {
leftMenuFlyoutHeight = () => this._dashUIHeight;
propertiesWidth = () => Math.max(0, Math.min(this._dashUIWidth - 50, CurrentUserUtils.propertiesWidth || 0));
propertiesHeight = () => this._dashUIHeight;
- mainDocViewWidth = () => this._dashUIWidth - this.propertiesWidth() - this.leftMenuWidth();
- mainDocViewHeight = () => this._dashUIHeight;
+ mainDocViewWidth = () => this._dashUIWidth - this.propertiesWidth() - this.leftMenuWidth() - this.leftMenuFlyoutWidth();
+ mainDocViewHeight = () => this._dashUIHeight - this.headerBarDocHeight();
componentDidMount() {
document.getElementById("root")?.addEventListener("scroll", e => ((ele) => ele.scrollLeft = ele.scrollTop = 0)(document.getElementById("root")!));
@@ -117,8 +122,8 @@ export class MainView extends React.Component {
}
this._sidebarContent.proto = undefined;
if (!MainView.Live) {
- DocServer.setPlaygroundFields(["dataTransition", "treeViewOpen", "autoHeight", "showSidebar", "sidebarWidthPercent", "viewTransition",
- "panX", "panY", "width", "height", "nativeWidth", "nativeHeight", "text-scrollHeight", "text-height", "hideMinimap",
+ DocServer.setPlaygroundFields(["dataTransition", "treeViewOpen", "showSidebar", "sidebarWidthPercent", "viewTransition",
+ "panX", "panY", "nativeWidth", "nativeHeight", "text-scrollHeight", "text-height", "hideMinimap",
"viewScale", "scrollTop", "hidden", "curPage", "viewType", "chromeHidden", "nativeWidth"]); // can play with these fields on someone else's
}
DocServer.GetRefField("rtfProto").then(proto => (proto instanceof Doc) && reaction(() => StrCast(proto.BROADCAST_MESSAGE), msg => msg && alert(msg)));
@@ -134,7 +139,7 @@ export class MainView extends React.Component {
window.addEventListener("paste", KeyManager.Instance.paste as any);
document.addEventListener("dash", (e: any) => { // event used by chrome plugin to tell Dash which document to focus on
const id = FormattedTextBox.GetDocFromUrl(e.detail);
- DocServer.GetRefField(id).then(doc => (doc instanceof Doc) ? DocumentManager.Instance.jumpToDocument(doc, false, undefined) : (null));
+ DocServer.GetRefField(id).then(doc => (doc instanceof Doc) ? DocumentManager.Instance.jumpToDocument(doc, false, undefined, []) : (null));
});
document.addEventListener("linkAnnotationToDash", Hypothesis.linkListener);
this.initEventListeners();
@@ -174,18 +179,18 @@ export class MainView extends React.Component {
fa.faClone, fa.faCloudUploadAlt, fa.faCommentAlt, fa.faCompressArrowsAlt, fa.faCut, fa.faEllipsisV, fa.faEraser, fa.faExclamation, fa.faFileAlt,
fa.faFileAudio, fa.faFileVideo, fa.faFilePdf, fa.faFilm, fa.faFilter, fa.faFont, fa.faGlobeAmericas, fa.faGlobeAsia, fa.faHighlighter, fa.faLongArrowAltRight, fa.faMousePointer,
fa.faMusic, fa.faObjectGroup, fa.faPause, fa.faPen, fa.faPenNib, fa.faPhone, fa.faPlay, fa.faPortrait, fa.faRedoAlt, fa.faStamp, fa.faStickyNote, fa.faArrowsAltV,
- fa.faTimesCircle, fa.faThumbtack, fa.faTree, fa.faTv, fa.faUndoAlt, fa.faVideo, fa.faAsterisk, fa.faBrain, fa.faImage, fa.faPaintBrush, fa.faTimes,
+ fa.faTimesCircle, fa.faThumbtack, fa.faTree, fa.faTv, fa.faUndoAlt, fa.faVideo, fa.faAsterisk, fa.faBrain, fa.faImage, fa.faPaintBrush, fa.faTimes, fa.faFlag,
fa.faEye, fa.faArrowsAlt, fa.faQuoteLeft, fa.faSortAmountDown, fa.faAlignLeft, fa.faAlignCenter, fa.faAlignRight, fa.faHeading, fa.faRulerCombined,
fa.faFillDrip, fa.faLink, fa.faUnlink, fa.faBold, fa.faItalic, fa.faClipboard, fa.faUnderline, fa.faStrikethrough, fa.faSuperscript, fa.faSubscript,
fa.faIndent, fa.faEyeDropper, fa.faPaintRoller, fa.faBars, fa.faBrush, fa.faShapes, fa.faEllipsisH, fa.faHandPaper, fa.faMap, fa.faUser, faHireAHelper as any,
fa.faTrashRestore, fa.faUsers, fa.faWrench, fa.faCog, fa.faMap, fa.faBellSlash, fa.faExpandAlt, fa.faArchive, fa.faBezierCurve, fa.faCircle, far.faCircle as any,
- fa.faLongArrowAltRight, fa.faPenFancy, fa.faAngleDoubleRight, faBuffer as any, fa.faExpand, fa.faUndo, fa.faSlidersH, fa.faAngleDoubleLeft, fa.faAngleUp,
- fa.faAngleDown, fa.faPlayCircle, fa.faClock, fa.faRocket, fa.faExchangeAlt, fa.faHashtag, fa.faAlignJustify, fa.faCheckSquare, fa.faListUl,
+ fa.faLongArrowAltRight, fa.faPenFancy, fa.faAngleDoubleRight, fa.faAngleDoubleDown, fa.faAngleDoubleLeft, fa.faAngleDoubleUp, faBuffer as any, fa.faExpand, fa.faUndo,
+ fa.faSlidersH, fa.faAngleUp, fa.faAngleDown, fa.faPlayCircle, fa.faClock, fa.faRocket, fa.faExchangeAlt, fa.faHashtag, fa.faAlignJustify, fa.faCheckSquare, fa.faListUl,
fa.faWindowMinimize, fa.faWindowRestore, fa.faTextWidth, fa.faTextHeight, fa.faClosedCaptioning, fa.faInfoCircle, fa.faTag, fa.faSyncAlt, fa.faPhotoVideo,
fa.faArrowAltCircleDown, fa.faArrowAltCircleUp, fa.faArrowAltCircleLeft, fa.faArrowAltCircleRight, fa.faStopCircle, fa.faCheckCircle, fa.faGripVertical,
fa.faSortUp, fa.faSortDown, fa.faTable, fa.faTh, fa.faThList, fa.faProjectDiagram, fa.faSignature, fa.faColumns, fa.faChevronCircleUp, fa.faUpload, fa.faBorderAll,
fa.faBraille, fa.faChalkboard, fa.faPencilAlt, fa.faEyeSlash, fa.faSmile, fa.faIndent, fa.faOutdent, fa.faChartBar, fa.faBan, fa.faPhoneSlash, fa.faGripLines,
- fa.faSave, fa.faBookmark, fa.faList, fa.faListOl, fa.faFolderPlus, fa.faLightbulb, fa.faBookOpen, fa.faMapMarkerAlt, fa.faSquareRootAlt]);
+ fa.faSave, fa.faBookmark, fa.faList, fa.faListOl, fa.faFolderPlus, fa.faLightbulb, fa.faBookOpen, fa.faMapMarkerAlt, fa.faSearchPlus, fa.faVolumeUp, fa.faVolumeDown]);
this.initAuthenticationRouters();
}
@@ -245,8 +250,7 @@ export class MainView extends React.Component {
title: "TRAILS", childDontRegisterViews: true, _height: 100, _forceActive: true, boxShadow: "0 0", _lockedPosition: true, treeViewOpen: true, system: true
}));
}
- const pres = Docs.Create.PresDocument(new List<Doc>(),
- { title: "Untitled Trail", _viewType: CollectionViewType.Stacking, _fitWidth: true, _width: 400, _height: 500, targetDropAction: "alias", _chromeHidden: true, boxShadow: "0 0" });
+ const pres = Docs.Create.PresDocument({ title: "Untitled Trail", _viewType: CollectionViewType.Stacking, _fitWidth: true, _width: 400, _height: 500, targetDropAction: "alias", _chromeHidden: true, boxShadow: "0 0" });
CollectionDockingView.AddSplit(pres, "right");
this.userDoc.activePresentation = pres;
Doc.AddDocToList(this.userDoc.myTrails as Doc, "data", pres);
@@ -265,7 +269,7 @@ export class MainView extends React.Component {
title: "My Documents", _showTitle: "title", buttonMenu: true, buttonMenuDoc: newFolderButton, _height: 100,
treeViewHideTitle: true, _xMargin: 5, _yMargin: 5, _gridGap: 5, _forceActive: true, childDropAction: "alias",
treeViewTruncateTitleWidth: 150, ignoreClick: true,
- isFolder: true, treeViewType: "fileSystem", childHideLinkButton: true,
+ isFolder: true, treeViewType: TreeViewType.fileSystem, childHideLinkButton: true,
_lockedPosition: true, boxShadow: "0 0", childDontRegisterViews: true, targetDropAction: "proto", system: true,
explainer: "This is your file manager where you can create folders to keep track of documents independently of your dashboard."
}));
@@ -274,32 +278,72 @@ export class MainView extends React.Component {
Doc.AddDocToList(this.userDoc.myFilesystem as Doc, "data", folder);
}
+ @observable _exploreMode = false;
+ @computed get exploreMode() {
+ return () => this._exploreMode ? ScriptField.MakeScript("CollectionBrowseClick(documentView, clientX, clientY)",
+ { documentView: "any", clientX: "number", clientY: "number" })! : undefined;
+ }
+ headerBarScreenXf = () => new Transform(-this.leftScreenOffsetOfMainDocView - this.leftMenuFlyoutWidth(), -this.headerBarDocHeight(), 1);
+
+ @computed get headerBarDocView() {
+ return <div style={{ height: this.headerBarDocHeight() }}>
+ <DocumentView key="headerBarDoc"
+ Document={this.headerBarDoc}
+ DataDoc={undefined}
+ addDocument={undefined}
+ addDocTab={this.addDocTabFunc}
+ pinToPres={emptyFunction}
+ docViewPath={returnEmptyDoclist}
+ styleProvider={DefaultStyleProvider}
+ rootSelected={returnTrue}
+ removeDocument={returnFalse}
+ fitContentsToDoc={returnTrue}
+ isDocumentActive={returnTrue} // headerBar is always documentActive (ie, the docView gets pointer events)
+ isContentActive={returnTrue} // headerBar is awlays contentActive which means its items are always documentActive
+ ScreenToLocalTransform={this.headerBarScreenXf}
+ childHideResizeHandles={returnTrue}
+ hideResizeHandles={true}
+ PanelWidth={this.headerBarDocWidth}
+ PanelHeight={this.headerBarDocHeight}
+ renderDepth={0}
+ focus={DocUtils.DefaultFocus}
+ whenChildContentsActiveChanged={emptyFunction}
+ bringToFront={emptyFunction}
+ docFilters={returnEmptyFilter}
+ docRangeFilters={returnEmptyFilter}
+ searchFilterDocs={returnEmptyDoclist}
+ ContainingCollectionView={undefined}
+ ContainingCollectionDoc={undefined}
+ /></div>;
+ }
@computed get mainDocView() {
- return <DocumentView key="main"
- Document={this.mainContainer!}
- DataDoc={undefined}
- addDocument={undefined}
- addDocTab={this.addDocTabFunc}
- pinToPres={emptyFunction}
- docViewPath={returnEmptyDoclist}
- layerProvider={undefined}
- styleProvider={undefined}
- rootSelected={returnTrue}
- isContentActive={returnTrue}
- removeDocument={undefined}
- ScreenToLocalTransform={Transform.Identity}
- PanelWidth={this.mainDocViewWidth}
- PanelHeight={this.mainDocViewHeight}
- focus={DocUtils.DefaultFocus}
- whenChildContentsActiveChanged={emptyFunction}
- bringToFront={emptyFunction}
- docFilters={returnEmptyFilter}
- docRangeFilters={returnEmptyFilter}
- searchFilterDocs={returnEmptyDoclist}
- ContainingCollectionView={undefined}
- ContainingCollectionDoc={undefined}
- renderDepth={-1}
- />;
+ return <>
+ {this.headerBarDocView}
+ <DocumentView key="main"
+ Document={this.mainContainer!}
+ DataDoc={undefined}
+ addDocument={undefined}
+ addDocTab={this.addDocTabFunc}
+ pinToPres={emptyFunction}
+ docViewPath={returnEmptyDoclist}
+ styleProvider={undefined}
+ rootSelected={returnTrue}
+ isContentActive={returnTrue}
+ removeDocument={undefined}
+ ScreenToLocalTransform={Transform.Identity}
+ PanelWidth={this.mainDocViewWidth}
+ PanelHeight={this.mainDocViewHeight}
+ focus={DocUtils.DefaultFocus}
+ whenChildContentsActiveChanged={emptyFunction}
+ bringToFront={emptyFunction}
+ docFilters={returnEmptyFilter}
+ docRangeFilters={returnEmptyFilter}
+ searchFilterDocs={returnEmptyDoclist}
+ ContainingCollectionView={undefined}
+ ContainingCollectionDoc={undefined}
+ suppressSetHeight={true}
+ renderDepth={-1}
+ /></>;
}
@computed get dockingContent() {
@@ -328,11 +372,23 @@ export class MainView extends React.Component {
this.closeFlyout);
}
- sidebarScreenToLocal = () => new Transform(0, -this.topOfMainDoc, 1);
+ sidebarScreenToLocal = () => new Transform(0, -this.topOfSidebarDoc, 1);
mainContainerXf = () => this.sidebarScreenToLocal().translate(-this.leftScreenOffsetOfMainDocView, 0);
- addDocTabFunc = (doc: Doc, where: string): boolean => {
- return where === "close" ? CollectionDockingView.CloseSplit(doc) :
- doc.dockingConfig ? CurrentUserUtils.openDashboard(Doc.UserDoc(), doc) : CollectionDockingView.AddSplit(doc, "right");
+ addDocTabFunc = (doc: Doc, location: string): boolean => {
+ const locationFields = doc._viewType === CollectionViewType.Docking ? ["dashboard"] : location.split(":");
+ const locationParams = locationFields.length > 1 ? locationFields[1] : "";
+ if (doc.dockingConfig) return CurrentUserUtils.openDashboard(Doc.UserDoc(), doc);
+ switch (locationFields[0]) {
+ case "dashboard": return CurrentUserUtils.openDashboard(Doc.UserDoc(), doc);
+ case "close": return CollectionDockingView.CloseSplit(doc, locationParams);
+ case "fullScreen": return CollectionDockingView.OpenFullScreen(doc);
+ case "lightbox": return LightboxView.AddDocTab(doc, location);
+ case "toggle": return CollectionDockingView.ToggleSplit(doc, locationParams);
+ case "inPlace":
+ case "add":
+ default:
+ return CollectionDockingView.AddSplit(doc, locationParams);
+ }
}
@@ -349,8 +405,7 @@ export class MainView extends React.Component {
addDocTab={this.addDocTabFunc}
pinToPres={emptyFunction}
docViewPath={returnEmptyDoclist}
- layerProvider={undefined}
- styleProvider={this._sidebarContent.proto === Doc.UserDoc().myDashboards ? DashboardStyleProvider : DefaultStyleProvider}
+ styleProvider={this._sidebarContent.proto === Doc.UserDoc().myDashboards || this._sidebarContent.proto === Doc.UserDoc().myFilesystem ? DashboardStyleProvider : DefaultStyleProvider}
rootSelected={returnTrue}
removeDocument={returnFalse}
ScreenToLocalTransform={this.mainContainerXf}
@@ -390,7 +445,6 @@ export class MainView extends React.Component {
docViewPath={returnEmptyDoclist}
focus={DocUtils.DefaultFocus}
styleProvider={DefaultStyleProvider}
- layerProvider={undefined}
isContentActive={returnTrue}
whenChildContentsActiveChanged={emptyFunction}
bringToFront={emptyFunction}
@@ -441,13 +495,23 @@ export class MainView extends React.Component {
<FontAwesomeIcon icon={this.propertiesWidth() < 10 ? "chevron-left" : "chevron-right"} color={this.colorScheme === ColorScheme.Dark ? Colors.WHITE : Colors.BLACK} size="sm" />
</div>
<div className="properties-container" style={{ width: this.propertiesWidth() }}>
- {this.propertiesWidth() < 10 ? (null) : <PropertiesView styleProvider={DefaultStyleProvider} width={this.propertiesWidth()} height={this.propertiesHeight()} />}
+ {this.propertiesWidth() < 10 ? (null) : <PropertiesView styleProvider={DefaultStyleProvider} addDocTab={this.addDocTabFunc} width={this.propertiesWidth()} height={this.propertiesHeight()} />}
</div>
</div>
</div>
</>;
}
+ @computed get headerBar() {
+ return !this.userDoc ? (null) :
+ <div className="mainView-dashboardArea" style={{
+ height: this.headerBarDocHeight(),
+ width: "100%",
+ }} >
+ {this.headerBarDocView}
+ </div>;
+ }
+
@computed get mainDashboardArea() {
return !this.userDoc ? (null) :
<div className="mainView-dashboardArea" ref={r => {
@@ -504,7 +568,6 @@ export class MainView extends React.Component {
dropAction={"alias"}
setHeight={returnFalse}
styleProvider={DefaultStyleProvider}
- layerProvider={undefined}
rootSelected={returnTrue}
bringToFront={emptyFunction}
select={emptyFunction}
@@ -563,13 +626,6 @@ export class MainView extends React.Component {
</svg>;
}
- @computed get topbar() {
- TraceMobx();
- return <div className="mainView-topbar">
- <TopBar />
- </div>;
- }
-
@computed get invisibleWebBox() { // see note under the makeLink method in HypothesisUtils.ts
return !DocumentLinksButton.invisibleWebDoc ? null :
<div className="mainView-invisibleWebRef" ref={DocumentLinksButton.invisibleWebRef}>
@@ -579,7 +635,6 @@ export class MainView extends React.Component {
ContainingCollectionDoc={undefined}
Document={DocumentLinksButton.invisibleWebDoc}
dropAction={"move"}
- layerProvider={undefined}
styleProvider={undefined}
isSelected={returnFalse}
select={returnFalse}
@@ -616,11 +671,11 @@ export class MainView extends React.Component {
<CaptureManager />
<GroupManager />
<GoogleAuthenticationManager />
- <DocumentDecorations boundsLeft={this.leftScreenOffsetOfMainDocView} boundsTop={this.topOfMainDoc} PanelWidth={this._windowWidth} PanelHeight={this._windowHeight} />
+ <DocumentDecorations boundsLeft={this.leftScreenOffsetOfMainDocView} boundsTop={this.topOfHeaderBarDoc} PanelWidth={this._windowWidth} PanelHeight={this._windowHeight} />
<ComponentDecorations boundsLeft={this.leftScreenOffsetOfMainDocView} boundsTop={this.topOfMainDocContent} />
- {this.topbar}
+ <TopBar />
{LinkDescriptionPopup.descriptionPopup ? <LinkDescriptionPopup /> : null}
- {DocumentLinksButton.LinkEditorDocView ? <LinkMenu docView={DocumentLinksButton.LinkEditorDocView} changeFlyout={emptyFunction} /> : (null)}
+ {DocumentLinksButton.LinkEditorDocView ? <LinkMenu clearLinkEditor={action(() => DocumentLinksButton.LinkEditorDocView = undefined)} docView={DocumentLinksButton.LinkEditorDocView} /> : (null)}
{LinkDocPreview.LinkInfo ? <LinkDocPreview {...LinkDocPreview.LinkInfo} /> : (null)}
<div style={{ position: "relative", display: LightboxView.LightboxDoc ? "none" : undefined, zIndex: 2001 }} >
<CollectionMenu panelWidth={this.topMenuWidth} panelHeight={this.topMenuHeight} />
@@ -633,6 +688,7 @@ export class MainView extends React.Component {
<ContextMenu />
<RadialMenu />
<AnchorMenu />
+ <DashFieldViewMenu />
<MarqueeOptionsMenu />
<OverlayView />
<TimelineMenu />
@@ -662,7 +718,6 @@ export class MainView extends React.Component {
rootSelected={returnFalse}
renderDepth={0}
setHeight={returnFalse}
- layerProvider={undefined}
styleProvider={undefined}
addDocTab={returnFalse}
pinToPres={returnFalse}