aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/collections/TreeView.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views/collections/TreeView.tsx')
-rw-r--r--src/client/views/collections/TreeView.tsx100
1 files changed, 52 insertions, 48 deletions
diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx
index f69aea2a7..b10a521ca 100644
--- a/src/client/views/collections/TreeView.tsx
+++ b/src/client/views/collections/TreeView.tsx
@@ -1,15 +1,12 @@
-/* eslint-disable jsx-a11y/no-static-element-interactions */
-/* eslint-disable jsx-a11y/no-noninteractive-element-interactions */
-/* eslint-disable jsx-a11y/click-events-have-key-events */
import { IconProp } from '@fortawesome/fontawesome-svg-core';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { IconButton, Size } from 'browndash-components';
-import { IReactionDisposer, action, computed, makeObservable, observable, reaction } from 'mobx';
+import { IReactionDisposer, action, computed, makeObservable, observable, reaction, runInAction } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
-import { ClientUtils, lightOrDark, return18, returnEmptyDoclist, returnEmptyFilter, returnEmptyString, returnFalse, returnTrue, returnZero, setupMoveUpEvents, simulateMouseClick } from '../../../ClientUtils';
+import { ClientUtils, lightOrDark, return18, returnEmptyFilter, returnEmptyString, returnFalse, returnTrue, returnZero, setupMoveUpEvents, simulateMouseClick } from '../../../ClientUtils';
import { emptyFunction } from '../../../Utils';
-import { Doc, DocListCast, Field, FieldResult, FieldType, Opt, StrListCast } from '../../../fields/Doc';
+import { Doc, DocListCast, Field, FieldType, Opt, StrListCast, returnEmptyDoclist } from '../../../fields/Doc';
import { DocData } from '../../../fields/DocSymbols';
import { Id } from '../../../fields/FieldSymbols';
import { List } from '../../../fields/List';
@@ -41,14 +38,15 @@ import { CollectionView } from './CollectionView';
import { TreeSort } from './TreeSort';
import './TreeView.scss';
+// eslint-disable-next-line @typescript-eslint/no-var-requires
const { TREE_BULLET_WIDTH } = require('../global/globalCssVariables.module.scss'); // prettier-ignore
export interface TreeViewProps {
treeView: CollectionTreeView;
// eslint-disable-next-line no-use-before-define
parentTreeView: TreeView | CollectionTreeView | undefined;
- observeHeight: (ref: any) => void;
- unobserveHeight: (ref: any) => void;
+ observeHeight: (ref: HTMLDivElement) => void;
+ unobserveHeight: (ref: HTMLDivElement) => void;
prevSibling?: Doc;
Document: Doc;
dataDoc?: Doc;
@@ -188,7 +186,7 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> {
moving: boolean = false;
@undoBatch move = (doc: Doc | Doc[], target: Doc | undefined, addDoc: (doc: Doc | Doc[]) => boolean) => {
if (this.Document !== target && addDoc !== returnFalse) {
- const canAdd1 = (this._props.parentTreeView as any).dropping || !(ComputedField.WithoutComputed(() => FieldValue(this._props.parentTreeView?.Document.data)) instanceof ComputedField);
+ const canAdd1 = (this._props.parentTreeView as TreeView).dropping || !(ComputedField.WithoutComputed(() => FieldValue(this._props.parentTreeView?.Document.data)) instanceof ComputedField);
// bcz: this should all be running in a Temp undo batch instead of hackily testing for returnFalse
if (canAdd1 && this._props.removeDoc?.(doc) === true) {
@@ -251,7 +249,7 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> {
return [];
}
- const runningChildren: FieldResult[] = [];
+ const runningChildren: Doc[] = [];
childList.forEach(child => {
if (child.runProcess && TreeView.GetRunningChildren.get(child)) {
if (child.runProcess) {
@@ -263,7 +261,7 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> {
return runningChildren;
};
- static GetRunningChildren = new Map<Doc, any>();
+ static GetRunningChildren = new Map<Doc, () => Doc[]>();
static ToggleChildrenRun = new Map<Doc, () => void>();
constructor(props: TreeViewProps) {
super(props);
@@ -285,7 +283,7 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> {
TreeView.GetRunningChildren.set(this.Document, () => this.getRunningChildren(this.childDocs));
}
- _treeEle: any;
+ _treeEle: HTMLDivElement | null = null;
protected createTreeDropTarget = (ele: HTMLDivElement) => {
this._treedropDisposer?.();
ele && ((this._treedropDisposer = DragManager.MakeDropTarget(ele, this.treeDrop.bind(this), this.Document, this.preTreeDrop.bind(this))), this.Document);
@@ -472,7 +470,7 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> {
refTransform = (ref: HTMLElement | undefined | null) => {
if (!ref) return this.ScreenToLocalTransform();
const { translateX, translateY, scale } = ClientUtils.GetScreenTransform(ref);
- return new Transform(-translateX, -translateY, 1).scale(1/scale);
+ return new Transform(-translateX, -translateY, 1).scale(1 / scale);
};
docTransform = () => this.refTransform(this._dref?.ContentDiv);
getTransform = () => this.refTransform(this._tref.current);
@@ -524,7 +522,7 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> {
return toList(docs).reduce((flg, iDoc) => flg && innerAdd(iDoc), true as boolean);
};
contentElement = TreeView.GetChildElements(
- toList(contents as any),
+ contents instanceof Doc ? [contents] : DocListCast(contents),
this.treeView,
this,
doc,
@@ -572,9 +570,11 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> {
rows.push(
<div style={{ display: 'flex', overflow: 'auto' }} key={key}>
<span
- ref={action((r: any) => {
- if (r) leftOffset.width = r.getBoundingClientRect().width;
- })}
+ ref={r =>
+ runInAction(() => {
+ if (r) leftOffset.width = r.getBoundingClientRect().width;
+ })
+ }
style={{ fontWeight: 'bold' }}>
{key + ':'}
&nbsp;
@@ -608,7 +608,7 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> {
return rows;
}
- _renderTimer: any;
+ _renderTimer: NodeJS.Timeout | undefined;
@observable _renderCount = 1;
@computed get renderContent() {
TraceMobx();
@@ -754,7 +754,7 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> {
}
get onCheckedClick() {
- return this.Document.type === DocumentType.COL ? undefined : this._props.onCheckedClick?.() ?? ScriptCast(this.Document.onCheckedClick);
+ return this.Document.type === DocumentType.COL ? undefined : (this._props.onCheckedClick?.() ?? ScriptCast(this.Document.onCheckedClick));
}
@action
@@ -777,9 +777,9 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> {
@computed get renderBullet() {
TraceMobx();
- const iconType = this.treeView._props.styleProvider?.(this.Document, this.treeView._props, StyleProp.TreeViewIcon + (this.treeViewOpen ? ':treeOpen' : !this.childDocs.length ? ':empty' : '')) || 'question';
+ const iconType = (this.treeView._props.styleProvider?.(this.Document, this.treeView._props, StyleProp.TreeViewIcon + (this.treeViewOpen ? ':treeOpen' : !this.childDocs.length ? ':empty' : '')) as string) || 'question';
const color = SettingsManager.userColor;
- const checked = this.onCheckedClick ? this.Document.treeView_Checked ?? 'unchecked' : undefined;
+ const checked = this.onCheckedClick ? (this.Document.treeView_Checked ?? 'unchecked') : undefined;
return (
<div
className={`bullet${this.treeView.outlineMode ? '-outline' : ''}`}
@@ -789,7 +789,7 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> {
style={
this.treeView.outlineMode
? {
- opacity: this.titleStyleProvider?.(this.Document, this.treeView._props, StyleProp.Opacity),
+ opacity: this.titleStyleProvider?.(this.Document, this.treeView._props, StyleProp.Opacity) as number,
}
: {
pointerEvents: this._props.isContentActive() ? 'all' : undefined,
@@ -829,7 +829,7 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> {
@action
expandNextviewType = () => {
if (this.treeViewOpen && !this.Document.isFolder && !this.treeView.outlineMode && !this.Document.treeView_ExpandedViewLock) {
- const next = (modes: any[]) => modes[(modes.indexOf(StrCast(this.treeViewExpandedView)) + 1) % modes.length];
+ const next = (modes: string[]) => modes[(modes.indexOf(StrCast(this.treeViewExpandedView)) + 1) % modes.length];
this.Document.treeView_ExpandedView = next(this.validExpandViewTypes);
}
this.treeViewOpen = true;
@@ -897,13 +897,13 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> {
onChildDoubleClick = () => ScriptCast(this.treeView.Document.treeView_ChildDoubleClick, !this.treeView.outlineMode ? this._openScript?.() : null);
refocus = () => this.treeView._props.focus(this.treeView.Document, {});
- ignoreEvent = (e: any) => {
+ ignoreEvent = (e: React.MouseEvent) => {
if (this._props.isContentActive(true)) {
e.stopPropagation();
e.preventDefault();
}
};
- titleStyleProvider = (doc: Doc | undefined, props: Opt<FieldViewProps>, property: string): any => {
+ titleStyleProvider = (doc: Doc | undefined, props: Opt<FieldViewProps>, property: string) => {
if (!doc || doc !== this.Document) return this._props?.treeView?._props.styleProvider?.(doc, props, property); // properties are inherited from the CollectionTreeView, not the hierarchical parent in the treeView
const { treeView } = this;
@@ -923,7 +923,7 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> {
style={{
// just render a title for a tree view label (identified by treeViewDoc being set in 'props')
maxWidth: props?.PanelWidth() || undefined,
- background: props?.styleProvider?.(doc, props, StyleProp.BackgroundColor),
+ background: props?.styleProvider?.(doc, props, StyleProp.BackgroundColor) as string,
outline: SnappingManager.IsDragging ? undefined: `solid ${highlightColor} ${highlightIndex}px`,
paddingLeft: NumCast(treeView.Document.childXPadding, NumCast(treeView._props.childXPadding, Doc.IsComicStyle(doc)?20:0)),
paddingRight: NumCast(treeView.Document.childXPadding, NumCast(treeView._props.childXPadding, Doc.IsComicStyle(doc)?20:0)),
@@ -938,7 +938,7 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> {
}
return treeView._props.styleProvider?.(doc, props, property);
};
- embeddedStyleProvider = (doc: Doc | undefined, props: Opt<FieldViewProps>, property: string): any => {
+ embeddedStyleProvider = (doc: Doc | undefined, props: Opt<FieldViewProps>, property: string) => {
if (property.startsWith(StyleProp.Decorations)) return null;
return this._props?.treeView?._props.styleProvider?.(doc, props, property); // properties are inherited from the CollectionTreeView, not the hierarchical parent in the treeView
};
@@ -990,28 +990,30 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> {
this._editTitle = e;
})}
GetValue={() => StrCast(this.Document.title)}
- OnTab={undoBatch((shift?: boolean) => {
+ OnTab={undoable((shift?: boolean) => {
if (!shift) this._props.indentDocument?.(true);
else this._props.outdentDocument?.(true);
- })}
- OnEmpty={undoBatch(() => this.treeView.outlineMode && this._props.removeDoc?.(this.Document))}
+ }, 'create new tree Doc')}
+ OnEmpty={undoable(() => this.treeView.outlineMode && this._props.removeDoc?.(this.Document), 'remove tree doc')}
OnFillDown={() => this.treeView.fileSysMode && this.makeFolder()}
- SetValue={undoBatch((value: string, shiftKey: boolean, enterKey: boolean) => {
+ SetValue={undoable((value: string, shiftKey: boolean, enterKey: boolean) => {
Doc.SetInPlace(this.Document, 'title', value, false);
- this.treeView.outlineMode && enterKey && this.makeTextCollection();
- })}
+ return this.treeView.outlineMode && enterKey && this.makeTextCollection();
+ }, 'set tree doc title')}
/>
) : (
<DocumentView
key="title"
- ref={action((r: any) => {
- this._docRef = r || undefined;
- if (this._docRef && TreeView._editTitleOnLoad?.id === this.Document[Id] && TreeView._editTitleOnLoad.parent === this._props.parentTreeView) {
- this._docRef.select(false);
- this.setEditTitle(this._docRef);
- TreeView._editTitleOnLoad = undefined;
- }
- })}
+ ref={r =>
+ runInAction(() => {
+ this._docRef = r || undefined;
+ if (this._docRef && TreeView._editTitleOnLoad?.id === this.Document[Id] && TreeView._editTitleOnLoad.parent === this._props.parentTreeView) {
+ this._docRef.select(false);
+ this.setEditTitle(this._docRef);
+ TreeView._editTitleOnLoad = undefined;
+ }
+ })
+ }
Document={this.Document}
fitWidth={returnTrue}
scriptContext={this}
@@ -1068,9 +1070,11 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> {
</div>
<div
className="treeView-rightButtons"
- ref={action((r: any) => {
- r && (this.headerEleWidth = r.getBoundingClientRect().width);
- })}>
+ ref={r =>
+ runInAction(() => {
+ r && (this.headerEleWidth = r.getBoundingClientRect().width);
+ })
+ }>
{this.titleButtons}
</div>
</>
@@ -1090,7 +1094,7 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> {
this,
e,
() => {
- (this._dref ?? this._docRef)?.startDragging(e.clientX, e.clientY, '' as any);
+ (this._dref ?? this._docRef)?.startDragging(e.clientX, e.clientY, undefined);
return true;
},
returnFalse,
@@ -1179,7 +1183,7 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> {
@computed get renderBorder() {
const sorting = StrCast(this.Document.treeView_SortCriterion, TreeSort.WhenAdded);
- const sortings = (this._props.styleProvider?.(this.Document, this.treeView._props, StyleProp.TreeViewSortings) ?? {}) as { [key: string]: { color: string; label: string } };
+ const sortings = (this._props.styleProvider?.(this.Document, this.treeView._props, StyleProp.TreeViewSortings) ?? {}) as { [key: string]: { color: string; icon: JSX.Element } };
return (
<div className={`treeView-border${this.treeView.outlineMode ? TreeViewType.outline : ''}`} style={{ borderColor: sortings[sorting]?.color }}>
{!this.treeViewOpen ? null : this.renderContent}
@@ -1272,8 +1276,8 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> {
firstLevel: boolean,
whenChildContentsActiveChanged: (isActive: boolean) => void,
dontRegisterView: boolean | undefined,
- observerHeight: (ref: any) => void,
- unobserveHeight: (ref: any) => void,
+ observerHeight: (ref: HTMLElement) => void,
+ unobserveHeight: (ref: HTMLElement) => void,
contextMenuItems: { script: ScriptField; filter: ScriptField; label: string; icon: string }[],
// TODO: [AL] add these
AddToMap?: (treeViewDoc: Doc, index: number[]) => void,