aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorbobzel <zzzman@gmail.com>2024-08-09 16:48:18 -0400
committerbobzel <zzzman@gmail.com>2024-08-09 16:48:18 -0400
commit762ac2bf354e4cc2c4b15f42502da939f5061646 (patch)
tree7c7b2a908d66b08372dbe13956d749b966487ce7 /src
parent4574b7f03ccc85c4bebdbfd9475788456086704f (diff)
a bunch more typing fixes.
Diffstat (limited to 'src')
-rw-r--r--src/client/util/BranchingTrailManager.tsx14
-rw-r--r--src/client/util/reportManager/ReportManager.scss12
-rw-r--r--src/client/views/ContextMenu.scss37
-rw-r--r--src/client/views/ContextMenu.tsx32
-rw-r--r--src/client/views/ContextMenuItem.tsx180
-rw-r--r--src/client/views/DictationOverlay.tsx2
-rw-r--r--src/client/views/DocViewUtils.ts1
-rw-r--r--src/client/views/DocumentButtonBar.tsx11
-rw-r--r--src/client/views/DocumentDecorations.tsx23
-rw-r--r--src/client/views/EditableView.tsx26
-rw-r--r--src/client/views/ExtractColors.ts2
-rw-r--r--src/client/views/FieldsDropdown.tsx8
-rw-r--r--src/client/views/GlobalKeyHandler.ts4
-rw-r--r--src/client/views/KeyphraseQueryView.scss8
-rw-r--r--src/client/views/KeyphraseQueryView.tsx32
-rw-r--r--src/client/views/MainViewModal.tsx2
-rw-r--r--src/client/views/ObservableReactComponent.tsx14
-rw-r--r--src/client/views/PreviewCursor.tsx51
-rw-r--r--src/client/views/PropertiesButtons.tsx19
-rw-r--r--src/client/views/PropertiesDocBacklinksSelector.tsx2
-rw-r--r--src/client/views/PropertiesDocContextSelector.tsx7
-rw-r--r--src/client/views/PropertiesSection.tsx4
-rw-r--r--src/client/views/PropertiesView.tsx102
-rw-r--r--src/client/views/SidebarAnnos.tsx10
-rw-r--r--src/client/views/StyleProvider.tsx11
-rw-r--r--src/client/views/TemplateMenu.tsx3
-rw-r--r--src/client/views/UndoStack.tsx2
-rw-r--r--src/client/views/collections/CollectionCarouselView.tsx3
-rw-r--r--src/client/views/collections/CollectionMenu.tsx44
-rw-r--r--src/client/views/collections/CollectionTreeView.tsx4
-rw-r--r--src/client/views/collections/CollectionView.tsx12
-rw-r--r--src/client/views/global/globalScripts.ts32
-rw-r--r--src/client/views/linking/LinkMenu.tsx4
-rw-r--r--src/client/views/linking/LinkMenuGroup.tsx2
-rw-r--r--src/client/views/linking/LinkMenuItem.tsx20
-rw-r--r--src/client/views/nodes/DataVizBox/DataVizBox.tsx2
-rw-r--r--src/client/views/nodes/DocumentContentsView.tsx4
-rw-r--r--src/client/views/nodes/FunctionPlotBox.tsx20
-rw-r--r--src/client/views/nodes/KeyValueBox.tsx3
-rw-r--r--src/client/views/nodes/KeyValuePair.tsx2
-rw-r--r--src/client/views/nodes/PDFBox.tsx6
-rw-r--r--src/client/views/nodes/formattedText/EquationView.tsx10
-rw-r--r--src/client/views/nodes/formattedText/FormattedTextBox.tsx6
43 files changed, 333 insertions, 460 deletions
diff --git a/src/client/util/BranchingTrailManager.tsx b/src/client/util/BranchingTrailManager.tsx
index 119d103c5..65336812d 100644
--- a/src/client/util/BranchingTrailManager.tsx
+++ b/src/client/util/BranchingTrailManager.tsx
@@ -15,18 +15,18 @@ export class BranchingTrailManager extends React.Component {
public static Instance: BranchingTrailManager;
// stack of the history
- @observable private slideHistoryStack: String[] = [];
- @observable private containsSet: Set<String> = new Set<String>();
+ @observable private slideHistoryStack: string[] = [];
+ @observable private containsSet: Set<string> = new Set<string>();
// docId to Doc map
- @observable private docIdToDocMap: Map<String, Doc> = new Map<String, Doc>();
+ @observable private docIdToDocMap: Map<string, Doc> = new Map<string, Doc>();
// prev pres to copmare with
- @observable private prevPresId: String | null = null;
- @action setPrevPres = action((newId: String | null) => {
+ @observable private prevPresId: string | null = null;
+ @action setPrevPres = action((newId: string | null) => {
this.prevPresId = newId;
});
- constructor(props: any) {
+ constructor(props: object) {
super(props);
makeObservable(this);
if (!BranchingTrailManager.Instance) {
@@ -48,7 +48,7 @@ export class BranchingTrailManager extends React.Component {
// Doc.AddToMyOverlay(hi);
};
- @action setSlideHistoryStack = action((newArr: String[]) => {
+ @action setSlideHistoryStack = action((newArr: string[]) => {
this.slideHistoryStack = newArr;
});
diff --git a/src/client/util/reportManager/ReportManager.scss b/src/client/util/reportManager/ReportManager.scss
index d82d7fdeb..fd343ac8e 100644
--- a/src/client/util/reportManager/ReportManager.scss
+++ b/src/client/util/reportManager/ReportManager.scss
@@ -96,12 +96,12 @@
transition: all 0.2s ease;
background: transparent;
- &:hover {
- // border-bottom-color: $text-gray;
- }
- &:focus {
- // border-bottom-color: #4476f7;
- }
+ // &:hover {
+ // // border-bottom-color: $text-gray;
+ // }
+ // &:focus {
+ // // border-bottom-color: #4476f7;
+ // }
}
// View issues
diff --git a/src/client/views/ContextMenu.scss b/src/client/views/ContextMenu.scss
index 232362c5c..4aaf2d03b 100644
--- a/src/client/views/ContextMenu.scss
+++ b/src/client/views/ContextMenu.scss
@@ -38,7 +38,12 @@
background: whitesmoke;
}
-.contextMenu-item {
+.contextMenuItem-Selected {
+ background: lightgoldenrodyellow;
+ border-style: none;
+}
+
+.contextMenuItem {
// width: 11vw; //10vw
height: 25px; //2vh
display: flex; //comment out to allow search icon to be inline with search text
@@ -59,7 +64,7 @@
text-transform: uppercase;
padding-right: 30px;
- .contextMenu-item-background {
+ .contextMenuItem-background {
width: 100%;
height: 100%;
position: absolute;
@@ -69,13 +74,7 @@
filter: opacity(0);
}
- &:hover {
- .contextMenu-item-background {
- filter: opacity(0.2) !important;
- }
- }
-
- .contextMenu-item-icon-background {
+ .contextMenuItem-icon {
pointer-events: all;
background-color: transparent;
width: 35px;
@@ -103,6 +102,8 @@
letter-spacing: 1px;
text-transform: uppercase;
padding-right: 30px;
+ align-items: center;
+ align-self: center;
}
.contextMenu-item:hover {
@@ -115,11 +116,6 @@
cursor: pointer;
}
-.contextMenu-itemSelected {
- background: lightgoldenrodyellow;
- border-style: none;
-}
-
.contextMenu-group {
// width: 11vw; //10vw
height: 30px; //2vh
@@ -145,23 +141,24 @@
padding-left: 5px;
}
-.contextMenu-inlineMenu {
- // border-top: solid 1px; //TODO:glr clean
-}
-
.contextMenu-description {
margin-left: 5px;
text-align: left;
display: inline; //need this?
}
-.search-icon {
+.contextMenu-search {
margin: 10px;
+ display: flex;
+ .contextMenu-searchIcon {
+ margin-right: 5px;
+ }
}
-.search {
+.contextMenu-searchInput {
margin-left: 10px;
padding-left: 10px;
border: solid black 1px;
border-radius: 5px;
+ width: 100%;
}
diff --git a/src/client/views/ContextMenu.tsx b/src/client/views/ContextMenu.tsx
index 05634f376..5edb5fc0d 100644
--- a/src/client/views/ContextMenu.tsx
+++ b/src/client/views/ContextMenu.tsx
@@ -8,7 +8,7 @@ import * as React from 'react';
import { DivHeight, DivWidth } from '../../ClientUtils';
import { SnappingManager } from '../util/SnappingManager';
import './ContextMenu.scss';
-import { ContextMenuItem, ContextMenuProps, OriginalMenuProps } from './ContextMenuItem';
+import { ContextMenuItem, ContextMenuProps } from './ContextMenuItem';
import { ObservableReactComponent } from './ObservableReactComponent';
@observer
@@ -148,13 +148,13 @@ export class ContextMenu extends ObservableReactComponent<{ noexpand?: boolean }
return wasOpen;
};
- @computed get filteredItems(): (OriginalMenuProps | string[])[] {
+ @computed get filteredItems(): (ContextMenuProps | string[])[] {
const searchString = this._searchString.toLowerCase().split(' ');
const matches = (descriptions: string[]) => searchString.every(s => descriptions.some(desc => desc.toLowerCase().includes(s)));
const flattenItems = (items: ContextMenuProps[], groupFunc: (groupName: string) => string[]) => {
- let eles: (OriginalMenuProps | string[])[] = [];
+ let eles: (ContextMenuProps | string[])[] = [];
- const leaves: OriginalMenuProps[] = [];
+ const leaves: ContextMenuProps[] = [];
items.forEach(item => {
const { description } = item;
const path = groupFunc(description);
@@ -165,7 +165,7 @@ export class ContextMenu extends ObservableReactComponent<{ noexpand?: boolean }
eles = eles.concat(children);
}
} else if (matches(path)) {
- leaves.push(item as OriginalMenuProps);
+ leaves.push(item as ContextMenuProps);
}
});
@@ -176,8 +176,8 @@ export class ContextMenu extends ObservableReactComponent<{ noexpand?: boolean }
return flattenItems(this._items.slice(), name => [name]);
}
- @computed get flatItems(): OriginalMenuProps[] {
- return this.filteredItems.filter(item => !Array.isArray(item)) as OriginalMenuProps[];
+ @computed get flatItems(): ContextMenuProps[] {
+ return this.filteredItems.filter(item => !Array.isArray(item)) as ContextMenuProps[];
}
@computed get menuItems() {
@@ -228,21 +228,11 @@ export class ContextMenu extends ObservableReactComponent<{ noexpand?: boolean }
color: SnappingManager.userColor,
}}>
{!this.itemsNeedSearch ? null : (
- <span className="search-icon">
- <span className="icon-background">
+ <span className="contextMenu-search">
+ <span className="contextMenu-searchIcon">
<FontAwesomeIcon icon="search" size="lg" />
</span>
- <input
- ref={this._searchRef}
- style={{ color: 'black' }}
- className="contextMenu-item contextMenu-description search"
- type="text"
- placeholder="Filter Menu..."
- value={this._searchString}
- onKeyDown={this.onKeyDown}
- onChange={this.onChange}
- autoFocus
- />
+ <input ref={this._searchRef} style={{ color: 'black' }} className="contextMenu-searchInput" type="text" placeholder="Filter Menu..." value={this._searchString} onKeyDown={this.onKeyDown} onChange={this.onChange} autoFocus />
</span>
)}
{this.menuItems}
@@ -264,7 +254,7 @@ export class ContextMenu extends ObservableReactComponent<{ noexpand?: boolean }
e.preventDefault();
} else if (e.key === 'Enter' || e.key === 'Tab') {
const item = this.flatItems[this._selectedIndex];
- if (item) {
+ if (item.event) {
item.event({ x: this.pageX, y: this.pageY });
} else {
// if (this._searchString.startsWith(this._defaultPrefix)) {
diff --git a/src/client/views/ContextMenuItem.tsx b/src/client/views/ContextMenuItem.tsx
index 3b87ea58b..5b4eb704b 100644
--- a/src/client/views/ContextMenuItem.tsx
+++ b/src/client/views/ContextMenuItem.tsx
@@ -8,32 +8,27 @@ import { SnappingManager } from '../util/SnappingManager';
import { UndoManager } from '../util/UndoManager';
import { ObservableReactComponent } from './ObservableReactComponent';
-export interface OriginalMenuProps {
+export interface ContextMenuProps {
+ icon: IconProp | JSX.Element;
description: string;
- event: (stuff?: unknown) => void;
- undoable?: boolean;
- noexpand?: boolean;
- subitems?: ContextMenuProps[];
- icon: IconProp | JSX.Element; // maybe should be optional (icon?)
- closeMenu?: () => void;
-}
-
-export interface SubmenuProps {
- description: string;
- // eslint-disable-next-line no-use-before-define
- subitems: ContextMenuProps[];
- noexpand?: boolean;
addDivider?: boolean;
- icon: IconProp; // maybe should be optional (icon?)
closeMenu?: () => void;
-}
-export type ContextMenuProps = OriginalMenuProps | SubmenuProps;
+ subitems?: ContextMenuProps[];
+ noexpand?: boolean; // whether to render the submenu items as a flyout from this item, or inline in place of this item
+
+ undoable?: boolean; // whether to wrap the event callback in an UndoBatch or not
+ event?: (stuff?: unknown) => void;
+}
@observer
export class ContextMenuItem extends ObservableReactComponent<ContextMenuProps & { selected?: boolean }> {
- @observable private _items: Array<ContextMenuProps> = [];
- @observable private overItem = false;
+ static readonly HOVER_TIMEOUT = 100;
+ _hoverTimeout?: NodeJS.Timeout;
+ _overPosY = 0;
+ _overPosX = 0;
+ @observable _items: ContextMenuProps[] = [];
+ @observable _overItem = false;
constructor(props: ContextMenuProps & { selected?: boolean }) {
super(props);
@@ -41,132 +36,63 @@ export class ContextMenuItem extends ObservableReactComponent<ContextMenuProps &
}
componentDidMount() {
- runInAction(() => {
- this._items.length = 0;
- });
- if ((this._props as SubmenuProps)?.subitems) {
- (this._props as SubmenuProps).subitems?.forEach(i => runInAction(() => this._items.push(i)));
- }
+ runInAction(() => this._items.push(...(this._props.subitems ?? [])));
}
handleEvent = async (e: React.MouseEvent<HTMLDivElement>) => {
- if ('event' in this._props) {
+ if (this._props.event) {
this._props.closeMenu?.();
- const batch = this._props.undoable !== false ? UndoManager.StartBatch(`Click Menu item: ${this._props.description}`) : undefined;
+ const batch = this._props.undoable ? UndoManager.StartBatch(`Click Menu item: ${this._props.description}`) : undefined;
await this._props.event({ x: e.clientX, y: e.clientY });
batch?.end();
}
};
- currentTimeout?: NodeJS.Timeout | undefined;
- static readonly timeout = 300;
- _overPosY = 0;
- _overPosX = 0;
+ setOverItem = (over: boolean) => {
+ this._hoverTimeout = setTimeout( action(() => { this._overItem = over; }), ContextMenuItem.HOVER_TIMEOUT ); // prettier-ignore
+ };
+
onPointerEnter = (e: React.MouseEvent) => {
- if (this.currentTimeout) {
- clearTimeout(this.currentTimeout);
- this.currentTimeout = undefined;
- }
- if (this.overItem) {
- return;
- }
+ this._hoverTimeout && clearTimeout(this._hoverTimeout);
this._overPosY = e.clientY;
this._overPosX = e.clientX;
- this.currentTimeout = setTimeout(
- action(() => {
- this.overItem = true;
- }),
- ContextMenuItem.timeout
- );
+ !this._overItem && this.setOverItem(true);
};
onPointerLeave = () => {
- if (this.currentTimeout) {
- clearTimeout(this.currentTimeout);
- this.currentTimeout = undefined;
- }
- if (!this.overItem) {
- return;
- }
- this.currentTimeout = setTimeout(
- action(() => {
- this.overItem = false;
- }),
- ContextMenuItem.timeout
- );
+ this._hoverTimeout && clearTimeout(this._hoverTimeout);
+ this._overItem && this.setOverItem(false);
};
- isJSXElement(val: unknown): val is JSX.Element {
- return React.isValidElement(val);
- }
+ renderItem = (submenu: JSX.Element[]) => {
+ const alignItems = this._overPosY < window.innerHeight / 3 ? 'flex-start' : this._overPosY > (window.innerHeight * 2) / 3 ? 'flex-end' : 'center';
+ const marginTop = this._overPosY < window.innerHeight / 3 ? '20px' : this._overPosY > (window.innerHeight * 2) / 3 ? '-20px' : '';
+ const marginLeft = window.innerWidth - this._overPosX - 50 > 0 ? '90%' : '20%';
- render() {
- if ('event' in this._props) {
- return (
- <div className={'contextMenu-item' + (this._props.selected ? ' contextMenu-itemSelected' : '')} onPointerDown={this.handleEvent}>
- {this._props.icon ? <span className="contextMenu-item-icon-background">{this.isJSXElement(this._props.icon) ? this._props.icon : <FontAwesomeIcon icon={this._props.icon} size="sm" />}</span> : null}
- <div className="contextMenu-description">{this._props.description.replace(':', '')}</div>
- <div
- className="contextMenu-item-background"
- style={{
- background: SnappingManager.userColor,
- }}
- />
- </div>
- );
- }
- if ('subitems' in this._props) {
- const where = !this.overItem ? '' : this._overPosY < window.innerHeight / 3 ? 'flex-start' : this._overPosY > (window.innerHeight * 2) / 3 ? 'flex-end' : 'center';
- const marginTop = !this.overItem ? '' : this._overPosY < window.innerHeight / 3 ? '20px' : this._overPosY > (window.innerHeight * 2) / 3 ? '-20px' : '';
+ return (
+ <div className={`contextMenuItem${this._props.selected ? '-Selected' : ''}`} //
+ onPointerEnter={this.onPointerEnter} onPointerLeave={this.onPointerLeave} onPointerDown={this.handleEvent}
+ style={{ alignItems, borderTop: this._props.addDivider ? 'solid 1px' : undefined }}
+ >
+ <div className="contextMenuItem-background" style={{ background: SnappingManager.userColor, filter: this._overItem ? 'opacity(0.2)' : '' }} />
+ <span className="contextMenuItem-icon" style={{ alignItems: 'center', alignSelf: 'center' }}>
+ {React.isValidElement(this._props.icon) ? this._props.icon : this._props.icon ? <FontAwesomeIcon icon={this._props.icon as IconProp} size="sm" /> : null}
+ </span>
+ <div className="contextMenu-description"> {this._props.description} </div>
+ {!submenu.length ? null : (
+ !this._overItem ?
+ <FontAwesomeIcon icon="angle-right" size="lg" style={{ position: 'absolute', right: '10px' }} /> : (
+ <div className="contextMenu-subMenu-cont" style={{ marginLeft, marginTop, background: SnappingManager.userBackgroundColor }}>
+ {submenu}
+ </div>
+ )
+ )}
+ </div>
+ ); // prettier-ignore
+ };
- // here
- const submenu = !this.overItem ? null : (
- <div
- className="contextMenu-subMenu-cont"
- style={{
- marginLeft: window.innerWidth - this._overPosX - 50 > 0 ? '90%' : '20%',
- marginTop,
- background: SnappingManager.userBackgroundColor,
- }}>
- {this._items.map(prop => (
- <ContextMenuItem {...prop} key={prop.description} closeMenu={this._props.closeMenu} />
- ))}
- </div>
- );
- if (!(this._props as SubmenuProps).noexpand) {
- return (
- <div className="contextMenu-inlineMenu">
- {this._items.map(prop => (
- <ContextMenuItem {...prop} key={prop.description} closeMenu={this._props.closeMenu} />
- ))}
- </div>
- );
- }
- return (
- <div
- className={'contextMenu-item' + (this._props.selected ? ' contextMenu-itemSelected' : '')}
- style={{ alignItems: where, borderTop: this._props.addDivider ? 'solid 1px' : undefined }}
- onMouseLeave={this.onPointerLeave}
- onMouseEnter={this.onPointerEnter}>
- {this._props.icon ? (
- <span className="contextMenu-item-icon-background" onMouseEnter={this.onPointerLeave} style={{ alignItems: 'center', alignSelf: 'center' }}>
- <FontAwesomeIcon icon={this._props.icon} size="sm" />
- </span>
- ) : null}
- <div className="contextMenu-description" onMouseEnter={this.onPointerEnter} style={{ alignItems: 'center', alignSelf: 'center' }}>
- {this._props.description}
- <FontAwesomeIcon icon="angle-right" size="lg" style={{ position: 'absolute', right: '10px' }} />
- </div>
- <div
- className="contextMenu-item-background"
- style={{
- background: SnappingManager.userColor,
- }}
- />
- {submenu}
- </div>
- );
- }
- return null;
+ render() {
+ const submenu = this._items.map(prop => <ContextMenuItem {...prop} key={prop.description} closeMenu={this._props.closeMenu} />);
+ return this.props.event || this._props.noexpand ? this.renderItem(submenu) : <div className="contextMenu-inlineMenu">{submenu}</div>;
}
}
diff --git a/src/client/views/DictationOverlay.tsx b/src/client/views/DictationOverlay.tsx
index b242acdba..e33049d3b 100644
--- a/src/client/views/DictationOverlay.tsx
+++ b/src/client/views/DictationOverlay.tsx
@@ -17,7 +17,7 @@ export class DictationOverlay extends React.Component {
// eslint-disable-next-line react/no-unused-class-component-methods
public hasActiveModal = false;
- constructor(props: any) {
+ constructor(props: object) {
super(props);
makeObservable(this);
DictationOverlay.Instance = this;
diff --git a/src/client/views/DocViewUtils.ts b/src/client/views/DocViewUtils.ts
index 1f5f29c7e..49a30aa08 100644
--- a/src/client/views/DocViewUtils.ts
+++ b/src/client/views/DocViewUtils.ts
@@ -6,6 +6,7 @@ import { Doc, SetActiveAudioLinker } from '../../fields/Doc';
import { DocUtils } from '../documents/DocUtils';
import { FieldViewProps } from './nodes/FieldView';
+// eslint-disable-next-line @typescript-eslint/no-namespace
export namespace DocViewUtils {
export const ActiveRecordings: { props: FieldViewProps; getAnchor: (addAsAnnotation: boolean) => Doc }[] = [];
diff --git a/src/client/views/DocumentButtonBar.tsx b/src/client/views/DocumentButtonBar.tsx
index 487868169..b778a4fb9 100644
--- a/src/client/views/DocumentButtonBar.tsx
+++ b/src/client/views/DocumentButtonBar.tsx
@@ -1,6 +1,3 @@
-/* eslint-disable jsx-a11y/control-has-associated-label */
-/* eslint-disable jsx-a11y/no-static-element-interactions */
-/* eslint-disable jsx-a11y/click-events-have-key-events */
import { IconLookup, IconProp } from '@fortawesome/fontawesome-svg-core';
import { faCalendarDays } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
@@ -20,7 +17,7 @@ import { DictationManager } from '../util/DictationManager';
import { DragManager } from '../util/DragManager';
import { dropActionType } from '../util/DropActionTypes';
import { SharingManager } from '../util/SharingManager';
-import { UndoManager, undoBatch } from '../util/UndoManager';
+import { UndoManager, undoable } from '../util/UndoManager';
import './DocumentButtonBar.scss';
import { ObservableReactComponent } from './ObservableReactComponent';
import { PinProps } from './PinFuncs';
@@ -33,12 +30,12 @@ import { OpenWhere } from './nodes/OpenWhere';
import { DashFieldView } from './nodes/formattedText/DashFieldView';
@observer
-export class DocumentButtonBar extends ObservableReactComponent<{ views: () => (DocumentView | undefined)[]; stack?: any }> {
+export class DocumentButtonBar extends ObservableReactComponent<{ views: () => (DocumentView | undefined)[]; stack?: unknown }> {
private _dragRef = React.createRef<HTMLDivElement>();
// eslint-disable-next-line no-use-before-define
public static Instance: DocumentButtonBar;
- constructor(props: any) {
+ constructor(props: { views: () => (DocumentView | undefined)[]; stack?: unknown }) {
super(props);
makeObservable(this);
DocumentButtonBar.Instance = this;
@@ -83,7 +80,7 @@ export class DocumentButtonBar extends ObservableReactComponent<{ views: () => (
<div
className="documentButtonBar-icon documentButtonBar-follow"
style={{ backgroundColor: followLink ? Colors.LIGHT_BLUE : Colors.DARK_GRAY, color: followLink ? Colors.BLACK : Colors.WHITE }}
- onClick={undoBatch(() => this._props.views().map(view => view?.toggleFollowLink(undefined, false)))}>
+ onClick={undoable(() => this._props.views().map(view => view?.toggleFollowLink(undefined, false)), 'follow link')}>
<div className="documentButtonBar-followTypes">
{followBtn(
true,
diff --git a/src/client/views/DocumentDecorations.tsx b/src/client/views/DocumentDecorations.tsx
index 93c3e3338..68970223a 100644
--- a/src/client/views/DocumentDecorations.tsx
+++ b/src/client/views/DocumentDecorations.tsx
@@ -34,6 +34,7 @@ import { DocumentView } from './nodes/DocumentView';
import { ImageBox } from './nodes/ImageBox';
import { OpenWhere, OpenWhereMod } from './nodes/OpenWhere';
import { FormattedTextBox } from './nodes/formattedText/FormattedTextBox';
+import { IconProp } from '@fortawesome/fontawesome-svg-core';
interface DocumentDecorationsProps {
PanelWidth: number;
@@ -145,7 +146,7 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora
titleEntered = (e: React.KeyboardEvent) => {
if (e.key === 'Enter') {
e.stopPropagation();
- (e.target as any).blur();
+ (e.target as HTMLElement).blur?.();
}
};
@@ -239,7 +240,7 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora
}
});
if (!this._iconifyBatch) {
- (document.activeElement as any).blur?.();
+ (document.activeElement as HTMLElement).blur?.();
this._iconifyBatch = UndoManager.StartBatch(forceDeleteOrIconify ? 'delete selected docs' : 'iconifying');
} else {
// eslint-disable-next-line no-param-reassign
@@ -254,7 +255,7 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora
setupMoveUpEvents(this, e, () => DragManager.StartWindowDrag?.(e, [DocumentView.SelectedDocs().lastElement()]) ?? false, emptyFunction, this.onMaximizeClick, false, false);
e.stopPropagation();
};
- onMaximizeClick = (e: any): void => {
+ onMaximizeClick = (e: PointerEvent): void => {
const selView = DocumentView.Selected()[0];
if (selView) {
if (e.ctrlKey) {
@@ -349,8 +350,10 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora
setupMoveUpEvents(
this,
e,
- (moveEv: PointerEvent, down: number[], delta: number[]) => // return false to keep getting events
- this.setRotateCenter(seldocview, [this.rotCenter[0] + delta[0], this.rotCenter[1] + delta[1]]) as any as boolean,
+ (moveEv: PointerEvent, down: number[], delta: number[]) => {
+ this.setRotateCenter(seldocview, [this.rotCenter[0] + delta[0], this.rotCenter[1] + delta[1]]);
+ return false;
+ },
action(() => { this._isRotating = false; }), // upEvent
action(() => { seldocview.Document._rotation_centerX = seldocview.Document._rotation_centerY = 0; }),
true
@@ -430,7 +433,7 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora
setupMoveUpEvents(this, e, this.onPointerMove, this.onPointerUp, emptyFunction);
e.stopPropagation();
const id = (this._resizeHdlId = e.currentTarget.className);
- const pad = id.includes('Left') || id.includes('Right') ? Number(getComputedStyle(e.target as any).width.replace('px', '')) / 2 : 0;
+ const pad = id.includes('Left') || id.includes('Right') ? Number(getComputedStyle(e.target as HTMLElement).width?.replace('px', '')) / 2 : 0;
const bounds = e.currentTarget.getBoundingClientRect();
this._offset = {
x: id.toLowerCase().includes('left') ? bounds.right - e.clientX - pad : bounds.left - e.clientX + pad, //
@@ -478,7 +481,7 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora
const scaleAspect = {x:scale.x === 1 && hasFixedAspect ? scale.y : scale.x, y: scale.x !== 1 && hasFixedAspect ? scale.x : scale.y};
DocumentView.Selected().forEach(docView =>
this.resizeView(docView, refPt, scaleAspect, { dragHdl, ctrlKey:e.ctrlKey })); // prettier-ignore
- await new Promise<any>(res => { setTimeout(() => { res(this._interactionLock = undefined)})});
+ await new Promise<void>(res => { setTimeout(() => { res(this._interactionLock = undefined)})});
}); // prettier-ignore
return false;
@@ -681,10 +684,10 @@ export class DocumentDecorations extends ObservableReactComponent<DocumentDecora
const collectionAcl = docView.containerViewPath?.()?.lastElement() ? GetEffectiveAcl(docView.containerViewPath?.().lastElement().dataDoc) : AclEdit;
return collectionAcl !== AclAdmin && collectionAcl !== AclEdit && GetEffectiveAcl(docView.Document) !== AclAdmin;
});
- const topBtn = (key: string, icon: string, pointerDown: undefined | ((e: React.PointerEvent) => void), click: undefined | ((e: any) => void), title: string) => (
+ const topBtn = (key: string, icon: IconProp, pointerDown: undefined | ((e: React.PointerEvent) => void), click: undefined | ((e: PointerEvent) => void), title: string) => (
<Tooltip key={key} title={<div className="dash-tooltip">{title}</div>} placement="top">
- <div className={`documentDecorations-${key}Button`} onContextMenu={e => e.preventDefault()} onPointerDown={pointerDown ?? (e => setupMoveUpEvents(this, e, returnFalse, emptyFunction, clickEv => click!(clickEv)))}>
- <FontAwesomeIcon icon={icon as any} />
+ <div className={`documentDecorations-${key}Button`} onContextMenu={e => e.preventDefault()} onPointerDown={pointerDown ?? (e => setupMoveUpEvents(this, e, returnFalse, emptyFunction, clickEv => click?.(clickEv)))}>
+ <FontAwesomeIcon icon={icon} />
</div>
</Tooltip>
);
diff --git a/src/client/views/EditableView.tsx b/src/client/views/EditableView.tsx
index 684b948af..e02e39b8b 100644
--- a/src/client/views/EditableView.tsx
+++ b/src/client/views/EditableView.tsx
@@ -1,10 +1,7 @@
-/* eslint-disable jsx-a11y/no-static-element-interactions */
-/* eslint-disable jsx-a11y/click-events-have-key-events */
import { action, IReactionDisposer, makeObservable, observable, reaction, runInAction } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
import * as Autosuggest from 'react-autosuggest';
-import { ObjectField } from '../../fields/ObjectField';
import './EditableView.scss';
import { DocumentIconContainer } from './nodes/DocumentIcon';
import { FieldView, FieldViewProps } from './nodes/FieldView';
@@ -29,7 +26,7 @@ export interface EditableProps {
/**
* The contents to render when not editing
*/
- contents: any;
+ contents: string;
fieldContents?: FieldViewProps;
fontStyle?: string;
fontSize?: number;
@@ -41,8 +38,8 @@ export interface EditableProps {
autosuggestProps?: {
resetValue: () => void;
value: string;
- onChange: (e: React.ChangeEvent, { newValue }: { newValue: string }) => void;
- autosuggestProps: Autosuggest.AutosuggestProps<string, any>;
+ onChange: (e: React.FormEvent, { newValue }: { newValue: string }) => void;
+ autosuggestProps: Autosuggest.AutosuggestProps<string, unknown>;
};
oneLine?: boolean; // whether to display the editable view as a single input line or as a textarea
allowCRs?: boolean; // can carriage returns be entered
@@ -112,8 +109,8 @@ export class EditableView extends ObservableReactComponent<EditableProps> {
}
onChange = (e: React.ChangeEvent) => {
- const targVal = (e.target as any).value;
- if (!(targVal.startsWith(':=') || targVal.startsWith('='))) {
+ const targVal = (e.target as HTMLSelectElement).value;
+ if (!(targVal?.startsWith(':=') || targVal?.startsWith('='))) {
this._overlayDisposer?.();
this._overlayDisposer = undefined;
} else if (!this._overlayDisposer) {
@@ -230,13 +227,11 @@ export class EditableView extends ObservableReactComponent<EditableProps> {
className: 'editableView-input',
onKeyDown: this.onKeyDown,
autoFocus: true,
- // @ts-ignore
- onBlur: e => this.finalizeEdit(e.currentTarget.value, false, true, false),
+ onBlur: e => this.finalizeEdit((e.currentTarget as HTMLSelectElement).value, false, true, false),
onPointerDown: this.stopPropagation,
onClick: this.stopPropagation,
onPointerUp: this.stopPropagation,
value: this._props.autosuggestProps.value,
- // @ts-ignore
onChange: this._props.autosuggestProps.onChange,
}}
/>
@@ -248,7 +243,6 @@ export class EditableView extends ObservableReactComponent<EditableProps> {
placeholder={this._props.placeholder}
onBlur={e => this.finalizeEdit(e.currentTarget.value, false, true, false)}
defaultValue={this._props.GetValue()}
- // eslint-disable-next-line jsx-a11y/no-autofocus
autoFocus
onChange={this.onChange}
onKeyDown={this.onKeyDown}
@@ -264,7 +258,6 @@ export class EditableView extends ObservableReactComponent<EditableProps> {
placeholder={this._props.placeholder}
onBlur={e => this.finalizeEdit(e.currentTarget.value, false, true, false)}
defaultValue={this._props.GetValue()}
- // eslint-disable-next-line jsx-a11y/no-autofocus
autoFocus
onChange={this.onChange}
onKeyDown={this.onKeyDown}
@@ -288,7 +281,7 @@ export class EditableView extends ObservableReactComponent<EditableProps> {
);
}
setTimeout(() => this._props.autosuggestProps?.resetValue());
- return this._props.contents instanceof ObjectField ? null : (
+ return (
<div
className={`editableView-container-editing${this._props.oneLine ? '-oneLine' : ''}`}
ref={this._ref}
@@ -308,10 +301,7 @@ export class EditableView extends ObservableReactComponent<EditableProps> {
fontStyle: this._props.fontStyle,
fontSize: this._props.fontSize,
}}>
- {
- // eslint-disable-next-line react/jsx-props-no-spreading
- this._props.fieldContents ? <FieldView {...this._props.fieldContents} /> : this.props.contents ? this._props.contents?.valueOf() : ''
- }
+ {this._props.fieldContents ? <FieldView {...this._props.fieldContents} /> : this._props.contents ? this._props.contents?.valueOf() : ''}
</span>
</div>
);
diff --git a/src/client/views/ExtractColors.ts b/src/client/views/ExtractColors.ts
index f6928c52a..eee1d3a04 100644
--- a/src/client/views/ExtractColors.ts
+++ b/src/client/views/ExtractColors.ts
@@ -126,7 +126,7 @@ export class ExtractColors {
let hue = 0;
let saturation = 0;
- let lightness = intensity;
+ const lightness = intensity;
if (area !== 0) {
saturation = area / (1 - Math.abs(2 * intensity - 1));
diff --git a/src/client/views/FieldsDropdown.tsx b/src/client/views/FieldsDropdown.tsx
index 0ea0ebd83..407031b40 100644
--- a/src/client/views/FieldsDropdown.tsx
+++ b/src/client/views/FieldsDropdown.tsx
@@ -29,7 +29,7 @@ interface fieldsDropdownProps {
@observer
export class FieldsDropdown extends ObservableReactComponent<fieldsDropdownProps> {
@observable _newField = '';
- constructor(props: any) {
+ constructor(props: fieldsDropdownProps) {
super(props);
makeObservable(this);
}
@@ -101,13 +101,13 @@ export class FieldsDropdown extends ObservableReactComponent<fieldsDropdownProps
}),
}}
placeholder={typeof this._props.placeholder === 'string' ? this._props.placeholder : this._props.placeholder?.()}
- options={options as any}
+ options={options}
isMulti={false}
- onChange={val => this._props.selectFunc((val as any as { value: string; label: string }).value)}
+ onChange={val => this._props.selectFunc((val as { value: string; label: string }).value)}
onKeyDown={e => {
if (e.key === 'Enter') {
runInAction(() => {
- this._props.selectFunc((this._newField = (e.nativeEvent.target as any)?.value));
+ this._props.selectFunc((this._newField = (e.nativeEvent.target as HTMLSelectElement)?.value));
});
}
e.stopPropagation();
diff --git a/src/client/views/GlobalKeyHandler.ts b/src/client/views/GlobalKeyHandler.ts
index 7d01bbabb..a85a03aab 100644
--- a/src/client/views/GlobalKeyHandler.ts
+++ b/src/client/views/GlobalKeyHandler.ts
@@ -56,7 +56,7 @@ export class KeyManager {
window.addEventListener('keydown', KeyManager.Instance.handle);
window.removeEventListener('keyup', KeyManager.Instance.unhandle);
window.addEventListener('keyup', KeyManager.Instance.unhandle);
- window.addEventListener('paste', KeyManager.Instance.paste as any);
+ window.addEventListener('paste', KeyManager.Instance.paste);
}
public unhandle = action((/* e: KeyboardEvent */) => {
@@ -330,7 +330,7 @@ export class KeyManager {
}
break;
case 'c':
- if ((document.activeElement as any)?.type !== 'text' && !AnchorMenu.Instance.Active && DocumentDecorations.Instance.Bounds.r - DocumentDecorations.Instance.Bounds.x > 2) {
+ if (!AnchorMenu.Instance.Active && DocumentDecorations.Instance.Bounds.r - DocumentDecorations.Instance.Bounds.x > 2) {
const bds = DocumentDecorations.Instance.Bounds;
const pt = DocumentView.Selected()[0]
.screenToViewTransform()
diff --git a/src/client/views/KeyphraseQueryView.scss b/src/client/views/KeyphraseQueryView.scss
deleted file mode 100644
index ac715e5e7..000000000
--- a/src/client/views/KeyphraseQueryView.scss
+++ /dev/null
@@ -1,8 +0,0 @@
-.fading {
- animation: fanOut 1s
-}
-
-@keyframes fanOut {
- from {opacity: 0;}
- to {opacity: 1;}
-} \ No newline at end of file
diff --git a/src/client/views/KeyphraseQueryView.tsx b/src/client/views/KeyphraseQueryView.tsx
deleted file mode 100644
index 81f004010..000000000
--- a/src/client/views/KeyphraseQueryView.tsx
+++ /dev/null
@@ -1,32 +0,0 @@
-/* eslint-disable jsx-a11y/label-has-associated-control */
-import { observer } from 'mobx-react';
-import * as React from 'react';
-import './KeyphraseQueryView.scss';
-
-// tslint:disable-next-line: class-name
-export interface KP_Props {
- keyphrases: string;
-}
-
-@observer
-export class KeyphraseQueryView extends React.Component<KP_Props> {
- render() {
- const keyterms = this.props.keyphrases.split(',');
- return (
- <div>
- <h5>Select queries to send:</h5>
- <form>
- {keyterms.map((kp: string) => (
- // return (<p>{"-" + kp}</p>);
- <p>
- <label>
- <input name="query" type="radio" />
- <span>{kp}</span>
- </label>
- </p>
- ))}
- </form>
- </div>
- );
- }
-}
diff --git a/src/client/views/MainViewModal.tsx b/src/client/views/MainViewModal.tsx
index a6dc5c62b..4a35805fb 100644
--- a/src/client/views/MainViewModal.tsx
+++ b/src/client/views/MainViewModal.tsx
@@ -1,5 +1,3 @@
-/* eslint-disable jsx-a11y/no-static-element-interactions */
-/* eslint-disable jsx-a11y/click-events-have-key-events */
/* eslint-disable react/require-default-props */
import { isDark } from 'browndash-components';
import { observer } from 'mobx-react';
diff --git a/src/client/views/ObservableReactComponent.tsx b/src/client/views/ObservableReactComponent.tsx
index 34da82b6c..bb7a07f0e 100644
--- a/src/client/views/ObservableReactComponent.tsx
+++ b/src/client/views/ObservableReactComponent.tsx
@@ -8,27 +8,27 @@ import JsxParser from 'react-jsx-parser';
* This is an abstract class that serves as the base for a PDF-style or Marquee-style
* menu. To use this class, look at PDFMenu.tsx or MarqueeOptionsMenu.tsx for an example.
*/
-export abstract class ObservableReactComponent<T> extends React.Component<T, {}> {
+export abstract class ObservableReactComponent<T> extends React.Component<T, object> {
@observable _props: React.PropsWithChildren<T>;
- constructor(props: any) {
+ constructor(props: React.PropsWithChildren<T>) {
super(props);
this._props = props;
makeObservable(this);
}
componentDidUpdate(prevProps: Readonly<T>): void {
Object.keys(prevProps)
- .filter(pkey => (prevProps as any)[pkey] !== (this.props as any)[pkey])
+ .filter(pkey => (prevProps as {[key:string]: unknown})[pkey] !== (this.props as {[key:string]: unknown})[pkey])
.forEach(action(pkey => {
- (this._props as any)[pkey] = (this.props as any)[pkey];
+ (this._props as {[key:string]: unknown})[pkey] = (this.props as {[key:string]: unknown})[pkey];
})); // prettier-ignore
}
}
class ObserverJsxParser1 extends JsxParser {
- constructor(props: any) {
+ constructor(props: object) {
super(props);
- observer(this as any);
+ observer(this as typeof JsxParser);
}
}
-export const ObserverJsxParser: typeof JsxParser = ObserverJsxParser1 as any;
+export const ObserverJsxParser = ObserverJsxParser1 as typeof JsxParser;
diff --git a/src/client/views/PreviewCursor.tsx b/src/client/views/PreviewCursor.tsx
index 034ade50b..7e597879d 100644
--- a/src/client/views/PreviewCursor.tsx
+++ b/src/client/views/PreviewCursor.tsx
@@ -7,13 +7,14 @@ import { Docs, DocumentOptions } from '../documents/Documents';
import { DocUtils } from '../documents/DocUtils';
import { ImageUtils } from '../util/Import & Export/ImageUtils';
import { Transform } from '../util/Transform';
-import { UndoManager, undoBatch } from '../util/UndoManager';
+import { UndoManager, undoable } from '../util/UndoManager';
import { ObservableReactComponent } from './ObservableReactComponent';
import './PreviewCursor.scss';
import { FormattedTextBox } from './nodes/formattedText/FormattedTextBox';
+import { StrCast } from '../../fields/Types';
@observer
-export class PreviewCursor extends ObservableReactComponent<{}> {
+export class PreviewCursor extends ObservableReactComponent<object> {
// eslint-disable-next-line no-use-before-define
static _instance: PreviewCursor;
public static get Instance() {
@@ -29,7 +30,7 @@ export class PreviewCursor extends ObservableReactComponent<{}> {
@observable _clickPoint: number[] = [];
@observable public Visible = false;
public Doc: Opt<Doc>;
- constructor(props: any) {
+ constructor(props: object) {
super(props);
makeObservable(this);
PreviewCursor._instance = this;
@@ -46,7 +47,7 @@ export class PreviewCursor extends ObservableReactComponent<{}> {
});
// tests for URL and makes web document
- const re: any = /^https?:\/\//g;
+ const re = /^https?:\/\//g;
const plain = e.clipboardData.getData('text/plain');
if (plain && newPoint) {
// tests for youtube and makes video document
@@ -64,17 +65,19 @@ export class PreviewCursor extends ObservableReactComponent<{}> {
} else if (re.test(plain)) {
const url = plain;
if (!url.startsWith(window.location.href)) {
- undoBatch(() =>
- this._addDocument?.(
- Docs.Create.WebDocument(url, {
- title: url,
- _width: 500,
- _height: 300,
- data_useCors: true,
- x: newPoint[0],
- y: newPoint[1],
- })
- )
+ undoable(
+ () =>
+ this._addDocument?.(
+ Docs.Create.WebDocument(url, {
+ title: url,
+ _width: 500,
+ _height: 300,
+ data_useCors: true,
+ x: newPoint[0],
+ y: newPoint[1],
+ })
+ ),
+ 'paste web doc'
)();
} else alert('cannot paste dash into itself');
} else if (plain.startsWith('__DashDocId(') || plain.startsWith('__DashCloneId(')) {
@@ -94,11 +97,11 @@ export class PreviewCursor extends ObservableReactComponent<{}> {
}
// pasting in images
else if (e.clipboardData.getData('text/html') !== '' && e.clipboardData.getData('text/html').includes('<img src=')) {
- const regEx: any = /<img src="(.*?)"/g;
- const arr: any[] = regEx.exec(e.clipboardData.getData('text/html'));
+ const regEx = /<img src="(.*?)"/g;
+ const arr = regEx.exec(e.clipboardData.getData('text/html'));
- if (newPoint) {
- undoBatch(() => {
+ if (newPoint && arr) {
+ undoable(() => {
const doc = Docs.Create.ImageDocument(arr[1], {
_width: 300,
title: arr[1],
@@ -107,7 +110,7 @@ export class PreviewCursor extends ObservableReactComponent<{}> {
});
ImageUtils.ExtractImgInfo(doc);
this._addDocument?.(doc);
- })();
+ }, 'paste image doc')();
}
} else if (e.clipboardData.items.length && newPoint) {
const batch = UndoManager.StartBatch('collection view drop');
@@ -196,8 +199,12 @@ export class PreviewCursor extends ObservableReactComponent<{}> {
}
render() {
return !this._clickPoint || !this.Visible ? null : (
- // eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex
- <div className="previewCursor" onBlur={this.onBlur} tabIndex={0} ref={e => e?.focus()} style={{ color: lightOrDark(this.Doc?.backgroundColor ?? 'white'), transform: `translate(${this._clickPoint[0]}px, ${this._clickPoint[1]}px)` }}>
+ <div
+ className="previewCursor"
+ onBlur={this.onBlur}
+ tabIndex={0}
+ ref={e => e?.focus()}
+ style={{ color: lightOrDark(StrCast(this.Doc?.backgroundColor, 'white')), transform: `translate(${this._clickPoint[0]}px, ${this._clickPoint[1]}px)` }}>
I
</div>
);
diff --git a/src/client/views/PropertiesButtons.tsx b/src/client/views/PropertiesButtons.tsx
index edf6df2b9..f346d4ba8 100644
--- a/src/client/views/PropertiesButtons.tsx
+++ b/src/client/views/PropertiesButtons.tsx
@@ -1,5 +1,3 @@
-/* eslint-disable jsx-a11y/no-static-element-interactions */
-/* eslint-disable jsx-a11y/click-events-have-key-events */
/* eslint-disable react/no-unused-class-component-methods */
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { Dropdown, DropdownType, IListItemProps, Toggle, ToggleType, Type } from 'browndash-components';
@@ -18,7 +16,7 @@ import { TfiBarChart } from 'react-icons/tfi';
import { Doc, Opt } from '../../fields/Doc';
import { DocData } from '../../fields/DocSymbols';
import { ScriptField } from '../../fields/ScriptField';
-import { BoolCast, ScriptCast } from '../../fields/Types';
+import { BoolCast, ScriptCast, StrCast } from '../../fields/Types';
import { ImageField } from '../../fields/URLField';
import { DocUtils, IsFollowLinkScript } from '../documents/DocUtils';
import { CollectionViewType, DocumentType } from '../documents/DocumentTypes';
@@ -32,7 +30,7 @@ import { OpenWhere } from './nodes/OpenWhere';
import { FormattedTextBox } from './nodes/formattedText/FormattedTextBox';
@observer
-export class PropertiesButtons extends React.Component<{}, {}> {
+export class PropertiesButtons extends React.Component {
// eslint-disable-next-line no-use-before-define
@observable public static Instance: PropertiesButtons;
@@ -314,13 +312,6 @@ export class PropertiesButtons extends React.Component<{}, {}> {
// );
// }
- @undoBatch
- handlePerspectiveChange = (e: any) => {
- this.selectedDoc && (this.selectedDoc._type_collection = e.target.value);
- DocumentView.Selected().forEach(docView => {
- docView.layoutDoc._type_collection = e.target.value;
- });
- };
@computed get onClickVal() {
const linkButton = IsFollowLinkScript(this.selectedDoc.onClick);
const followLoc = this.selectedDoc._followLinkLocation;
@@ -452,7 +443,7 @@ export class PropertiesButtons extends React.Component<{}, {}> {
else this.selectedDoc && DocUtils.makeCustomViewClicked(this.selectedDoc, undefined, 'onClick');
};
- propertyToggleBtn = (label: (on?: any) => string, property: string, tooltip: (on?: any) => string, icon: (on?: any) => any, onClick?: (dv: Opt<DocumentView>, doc: Doc, property: string) => void, useUserDoc?: boolean) => {
+ propertyToggleBtn = (label: (on?: unknown) => string, property: string, tooltip: (on?: unknown) => string, icon: (on?: unknown) => unknown, onClick?: (dv: Opt<DocumentView>, doc: Doc, property: string) => void, useUserDoc?: boolean) => {
const targetDoc = useUserDoc ? Doc.UserDoc() : this.selectedLayoutDoc;
const onPropToggle = (dv: Opt<DocumentView>, doc: Doc, prop: string) => {
(dv?.layoutDoc || doc)[prop] = !(dv?.layoutDoc || doc)[prop];
@@ -463,7 +454,7 @@ export class PropertiesButtons extends React.Component<{}, {}> {
tooltip={tooltip(BoolCast(targetDoc[property]))}
text={label(targetDoc?.[property])}
color={SettingsManager.userColor}
- icon={icon(targetDoc?.[property] as any)}
+ icon={icon(targetDoc?.[property]) as string}
iconPlacement="left"
align="flex-start"
fillWidth
@@ -484,7 +475,7 @@ export class PropertiesButtons extends React.Component<{}, {}> {
const isImage = layoutField instanceof ImageField;
const isMap = this.selectedDoc?.type === DocumentType.MAP;
const isCollection = this.selectedDoc?.type === DocumentType.COL;
- const isStacking = [CollectionViewType.Stacking, CollectionViewType.Masonry, CollectionViewType.NoteTaking].includes(this.selectedDoc?._type_collection as any);
+ const isStacking = [CollectionViewType.Stacking, CollectionViewType.Masonry, CollectionViewType.NoteTaking].includes(StrCast(this.selectedDoc?._type_collection) as CollectionViewType);
const isFreeForm = this.selectedDoc?._type_collection === CollectionViewType.Freeform;
const isTree = this.selectedDoc?._type_collection === CollectionViewType.Tree;
const toggle = (ele: JSX.Element | null, style?: React.CSSProperties) => (
diff --git a/src/client/views/PropertiesDocBacklinksSelector.tsx b/src/client/views/PropertiesDocBacklinksSelector.tsx
index edb55f341..e30d14eae 100644
--- a/src/client/views/PropertiesDocBacklinksSelector.tsx
+++ b/src/client/views/PropertiesDocBacklinksSelector.tsx
@@ -16,7 +16,7 @@ import { DocumentView } from './nodes/DocumentView';
type PropertiesDocBacklinksSelectorProps = {
Document: Doc;
- Stack?: any;
+ Stack?: string;
hideTitle?: boolean;
addDocTab(doc: Doc, location: OpenWhere): void;
};
diff --git a/src/client/views/PropertiesDocContextSelector.tsx b/src/client/views/PropertiesDocContextSelector.tsx
index 1fea36d16..f494ff16a 100644
--- a/src/client/views/PropertiesDocContextSelector.tsx
+++ b/src/client/views/PropertiesDocContextSelector.tsx
@@ -1,6 +1,3 @@
-/* eslint-disable jsx-a11y/no-static-element-interactions */
-/* eslint-disable jsx-a11y/click-events-have-key-events */
-/* eslint-disable jsx-a11y/anchor-is-valid */
import { computed, makeObservable } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
@@ -15,14 +12,14 @@ import { OpenWhere } from './nodes/OpenWhere';
type PropertiesDocContextSelectorProps = {
DocView?: DocumentView;
- Stack?: any;
+ Stack?: string;
hideTitle?: boolean;
addDocTab(doc: Doc, location: OpenWhere): void;
};
@observer
export class PropertiesDocContextSelector extends ObservableReactComponent<PropertiesDocContextSelectorProps> {
- constructor(props: any) {
+ constructor(props: PropertiesDocContextSelectorProps) {
super(props);
makeObservable(this);
}
diff --git a/src/client/views/PropertiesSection.tsx b/src/client/views/PropertiesSection.tsx
index b9a587719..12a46c7a4 100644
--- a/src/client/views/PropertiesSection.tsx
+++ b/src/client/views/PropertiesSection.tsx
@@ -1,5 +1,3 @@
-/* eslint-disable jsx-a11y/no-static-element-interactions */
-/* eslint-disable jsx-a11y/click-events-have-key-events */
/* eslint-disable react/require-default-props */
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { action, computed } from 'mobx';
@@ -12,7 +10,7 @@ export interface PropertiesSectionProps {
title: string;
children?: JSX.Element | string | null;
isOpen: boolean;
- setIsOpen: (bool: boolean) => any;
+ setIsOpen: (bool: boolean) => void;
onDoubleClick?: () => void;
}
diff --git a/src/client/views/PropertiesView.tsx b/src/client/views/PropertiesView.tsx
index 024db82a4..5952d6641 100644
--- a/src/client/views/PropertiesView.tsx
+++ b/src/client/views/PropertiesView.tsx
@@ -1,7 +1,4 @@
-/* eslint-disable jsx-a11y/click-events-have-key-events */
-/* eslint-disable jsx-a11y/no-static-element-interactions */
-/* eslint-disable prettier/prettier */
-import { IconLookup } from '@fortawesome/fontawesome-svg-core';
+import { IconLookup, IconProp } 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 '@mui/material';
@@ -12,6 +9,7 @@ import { observer } from 'mobx-react';
import * as React from 'react';
import { ColorResult, SketchPicker } from 'react-color';
import * as Icons from 'react-icons/bs'; // {BsCollectionFill, BsFillFileEarmarkImageFill} from "react-icons/bs"
+import ResizeObserver from 'resize-observer-polyfill';
import { ClientUtils, returnEmptyDoclist, returnEmptyFilter, returnEmptyString, returnFalse, returnTrue, setupMoveUpEvents } from '../../ClientUtils';
import { emptyFunction } from '../../Utils';
import { Doc, Field, FieldResult, FieldType, HierarchyMapping, NumListCast, Opt, ReverseHierarchyMap, StrListCast } from '../../fields/Doc';
@@ -44,8 +42,6 @@ import { StyleProviderFuncType } from './nodes/FieldView';
import { OpenWhere } from './nodes/OpenWhere';
import { PresBox, PresEffect, PresEffectDirection } from './nodes/trails';
-const _global = (window /* browser */ || global) /* node */ as any;
-
interface PropertiesViewProps {
width: number;
height: number;
@@ -59,7 +55,7 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
// eslint-disable-next-line no-use-before-define
public static Instance: PropertiesView | undefined;
- constructor(props: any) {
+ constructor(props: PropertiesViewProps) {
super(props);
makeObservable(this);
PropertiesView.Instance = this;
@@ -142,7 +138,7 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
return this.selectedDoc?.isGroup;
}
@computed get isStack() {
- return [CollectionViewType.Masonry, CollectionViewType.Multicolumn, CollectionViewType.Multirow, CollectionViewType.Stacking, CollectionViewType.NoteTaking].includes(this.selectedDoc?.type_collection as any);
+ return [CollectionViewType.Masonry, CollectionViewType.Multicolumn, CollectionViewType.Multirow, CollectionViewType.Stacking, CollectionViewType.NoteTaking].includes(this.selectedDoc?.type_collection as CollectionViewType);
}
rtfWidth = () => (!this.selectedLayoutDoc ? 0 : Math.min(NumCast(this.selectedLayoutDoc?._width), this._props.width - 20));
@@ -275,7 +271,7 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
@observable transform: Transform = Transform.Identity();
getTransform = () => this.transform;
propertiesDocViewRef = (ref: HTMLDivElement) => {
- const resizeObserver = new _global.ResizeObserver(
+ const resizeObserver = new ResizeObserver(
action(() => {
const cliRect = ref.getBoundingClientRect();
this.transform = new Transform(-cliRect.x, -cliRect.y, 1);
@@ -357,7 +353,7 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
* Handles the changing of a user's permissions from the permissions panel.
*/
@undoBatch
- changePermissions = (e: any, user: string) => {
+ changePermissions = (e: React.ChangeEvent<HTMLSelectElement>, user: string) => {
const docs = DocumentView.Selected().length < 2 ? [this.selectedDoc] : DocumentView.Selected().map(dv => (this.layoutDocAcls ? dv.layoutDoc : dv.dataDoc));
SharingManager.Instance.shareFromPropertiesSidebar(user, e.currentTarget.value as SharingPermissions, docs, this.layoutDocAcls);
};
@@ -456,7 +452,7 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
/**
* Sorting algorithm to sort users.
*/
- sortUsers = (u1: String, u2: String) => (u1 > u2 ? -1 : u1 === u2 ? 0 : 1);
+ sortUsers = (u1: string, u2: string) => (u1 > u2 ? -1 : u1 === u2 ? 0 : 1);
/**
* Sorting algorithm to sort groups.
@@ -711,7 +707,7 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
);
}
- inputBox = (key: string, value: any, setter: (val: string) => {}, title: string) => (
+ inputBox = (key: string, value: string | number | undefined, setter: (val: string) => void, title: string) => (
<div
className="inputBox"
style={{
@@ -721,17 +717,29 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
<div className="inputBox-title"> {title} </div>
<input className="inputBox-input" type="text" value={value} style={{ color: SnappingManager.userColor, backgroundColor: SnappingManager.userBackgroundColor }} onChange={e => setter(e.target.value)} onKeyDown={e => e.stopPropagation()} />
<div className="inputBox-button">
- <div className="inputBox-button-up" key="up2" onPointerDown={undoBatch(action(() => this.upDownButtons('up', key)))}>
+ <div
+ className="inputBox-button-up"
+ key="up2"
+ onPointerDown={undoable(
+ action(() => this.upDownButtons('up', key)),
+ 'down btn'
+ )}>
<FontAwesomeIcon icon="caret-up" size="sm" />
</div>
- <div className="inputbox-Button-down" key="down2" onPointerDown={undoBatch(action(() => this.upDownButtons('down', key)))}>
+ <div
+ className="inputbox-Button-down"
+ key="down2"
+ onPointerDown={undoable(
+ action(() => this.upDownButtons('down', key)),
+ 'up btn'
+ )}>
<FontAwesomeIcon icon="caret-down" size="sm" />
</div>
</div>
</div>
);
- inputBoxDuo = (key: string, value: any, setter: (val: string) => {}, title1: string, key2: string, value2: any, setter2: (val: string) => {}, title2: string) => (
+ inputBoxDuo = (key: string, value: string | number | undefined, setter: (val: string) => void, title1: string, key2: string, value2: string | number | undefined, setter2: (val: string) => void, title2: string) => (
<div className="inputBox-duo">
{this.inputBox(key, value, setter, title1)}
{title2 === '' ? null : this.inputBox(key2, value2, setter2, title2)}
@@ -841,7 +849,7 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
@observable private _fillBtn = false;
@observable private _lineBtn = false;
- private _lastDash: any = '2';
+ private _lastDash: string = '2';
@computed get colorFil() { return StrCast(this.selectedDoc?.[DocData].fillColor); } // prettier-ignore
set colorFil(value) { this.selectedDoc && (this.selectedDoc[DocData].fillColor = value || undefined); } // prettier-ignore
@@ -917,7 +925,7 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
);
}
- @computed get dashdStk() { return this.selectedDoc?.stroke_dash || ''; } // prettier-ignore
+ @computed get dashdStk() { return StrCast(this.selectedDoc?.stroke_dash); } // prettier-ignore
set dashdStk(value) {
value && (this._lastDash = value);
this.selectedDoc && (this.selectedDoc[DocData].stroke_dash = value ? this._lastDash : undefined);
@@ -939,14 +947,26 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
this.selectedDoc && (this.selectedDoc[DocData].stroke_endMarker = value);
}
- regInput = (key: string, value: any, setter: (val: string) => {}) => (
+ regInput = (key: string, value: string | number | undefined, setter: (val: string) => void) => (
<div className="inputBox">
<input className="inputBox-input" type="text" value={value} style={{ color: SnappingManager.userColor, backgroundColor: SnappingManager.userBackgroundColor }} onChange={e => setter(e.target.value)} />
<div className="inputBox-button">
- <div className="inputBox-button-up" key="up2" onPointerDown={undoBatch(action(() => this.upDownButtons('up', key)))}>
+ <div
+ className="inputBox-button-up"
+ key="up2"
+ onPointerDown={undoable(
+ action(() => this.upDownButtons('up', key)),
+ 'up'
+ )}>
<FontAwesomeIcon icon="caret-up" size="sm" />
</div>
- <div className="inputbox-Button-down" key="down2" onPointerDown={undoBatch(action(() => this.upDownButtons('down', key)))}>
+ <div
+ className="inputbox-Button-down"
+ key="down2"
+ onPointerDown={undoable(
+ action(() => this.upDownButtons('down', key)),
+ 'down'
+ )}>
<FontAwesomeIcon icon="caret-down" size="sm" />
</div>
</div>
@@ -1002,7 +1022,7 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
className="arrows-head-input"
type="checkbox"
checked={this.markHead !== ''}
- onChange={undoBatch(action(() => { this.markHead = this.markHead ? '' : 'arrow'; }))}
+ onChange={undoable(action(() => { this.markHead = this.markHead ? '' : 'arrow'; }), "change arrow head")}
/>
</div>
<div className="arrows-tail">
@@ -1012,8 +1032,8 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
className="arrows-tail-input"
type="checkbox"
checked={this.markTail !== ''}
- onChange={undoBatch(
- action(() => { this.markTail = this.markTail ? '' : 'arrow'; })
+ onChange={undoable(
+ action(() => { this.markTail = this.markTail ? '' : 'arrow'; }) ,"change arrow tail"
)}
/>
</div>
@@ -1044,7 +1064,8 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
setFinalNumber = () => {
this._sliderBatch?.end();
};
- getNumber = (label: string, unit: string, min: number, max: number, number: number, setNumber: any, autorange?: number, autorangeMinVal?: number) => (
+
+ getNumber = (label: string, unit: string, min: number, max: number, number: number, setNumber: (val: number) => void, autorange?: number, autorangeMinVal?: number) => (
<div key={label + (this.selectedDoc?.title ?? '')}>
<NumberInput formLabel={label} formLabelPlacement="left" type={Type.SEC} unit={unit} fillWidth color={this.color} number={number} setNumber={setNumber} min={min} max={max} />
<Slider
@@ -1234,7 +1255,7 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
}
@computed get description() {
- return Field.toString(this.selectedLink?.link_description as any as FieldType);
+ return Field.toString(this.selectedLink?.link_description as FieldType);
}
@computed get relationship() {
return StrCast(this.selectedLink?.link_relationship);
@@ -1332,7 +1353,7 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
<div
style={{ ...opts, border: direction === PresEffectDirection.Center ? `solid 2px ${color}` : undefined, borderRadius: '20%', cursor: 'pointer', gridColumn, gridRow, justifySelf: 'center', background: color, color: 'black' }}
onClick={() => this.changeEffectDirection(direction)}>
- {icon ? <FontAwesomeIcon icon={icon as any} /> : null}
+ {icon ? <FontAwesomeIcon icon={icon as IconProp} /> : null}
</div>
</Tooltip>
);
@@ -1368,7 +1389,7 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
e,
returnFalse,
emptyFunction,
- undoBatch(action(() => { this.selectedLink && (this.selectedLink[prop] = !this.selectedLink[prop]); })) // prettier-ignore
+ undoable(action(() => { this.selectedLink && (this.selectedLink[prop] = !this.selectedLink[prop]); }), `toggle prop: ${prop}`) // prettier-ignore
);
};
@@ -1385,17 +1406,17 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
return selAnchor ?? (this.selectedLink && this.destinationAnchor ? Doc.getOppositeAnchor(this.selectedLink, this.destinationAnchor) : this.selectedLink);
}
- toggleAnchorProp = (e: React.PointerEvent, prop: string, anchor?: Doc, value: any = true, ovalue: any = false, cb: (val: any) => any = val => val) => {
+ toggleAnchorProp = (e: React.PointerEvent, prop: string, anchor?: Doc, value: FieldType = true, ovalue: FieldType = false, cb: (val: FieldType) => void = val => val) => {
anchor &&
setupMoveUpEvents(
this,
e,
returnFalse,
emptyFunction,
- undoBatch(action(() => {
+ undoable(action(() => {
anchor[prop] = anchor[prop] === value ? ovalue : value;
- this.selectedDoc && cb(anchor[prop]);
- })) // prettier-ignore
+ this.selectedDoc && cb(anchor[prop] as boolean);
+ }), `toggle anchor prop: ${prop}`) // prettier-ignore
);
};
@@ -1433,7 +1454,7 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
}
// Converts seconds to ms and updates presTransition
- setZoom = (number: String, change?: number) => {
+ setZoom = (number: string, change?: number) => {
let scale = Number(number) / 100;
if (change) scale += change;
if (scale < 0.01) scale = 0.01;
@@ -1530,7 +1551,6 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
<div className="propertiesView-input inline">
<p>Play Target Audio</p>
{
- // eslint-disable-next-line jsx-a11y/control-has-associated-label
<button
type="button"
style={{ background: !this.sourceAnchor?.followLinkAudio ? '' : '#4476f7', borderRadius: 3 }}
@@ -1544,7 +1564,6 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
<div className="propertiesView-input inline">
<p>Play Target Video</p>
{
- // eslint-disable-next-line jsx-a11y/control-has-associated-label
<button
type="button"
style={{ background: !this.sourceAnchor?.followLinkVideo ? '' : '#4476f7', borderRadius: 3 }}
@@ -1558,7 +1577,6 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
<div className="propertiesView-input inline">
<p>Zoom Text Selections</p>
{
- // eslint-disable-next-line jsx-a11y/control-has-associated-label
<button
type="button"
style={{ background: !this.sourceAnchor?.followLinkZoomText ? '' : '#4476f7', borderRadius: 3 }}
@@ -1572,7 +1590,6 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
<div className="propertiesView-input inline">
<p>Toggle Follow to Outer Context</p>
{
- // eslint-disable-next-line jsx-a11y/control-has-associated-label
<button
type="button"
style={{ background: !this.sourceAnchor?.followLinkToOuterContext ? '' : '#4476f7', borderRadius: 3 }}
@@ -1586,7 +1603,6 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
<div className="propertiesView-input inline">
<p>Toggle Target (Show/Hide)</p>
{
- // eslint-disable-next-line jsx-a11y/control-has-associated-label
<button
type="button"
style={{ background: !this.sourceAnchor?.followLinkToggle ? '' : '#4476f7', borderRadius: 3 }}
@@ -1600,7 +1616,6 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
<div className="propertiesView-input inline">
<p>Ease Transitions</p>
{
- // eslint-disable-next-line jsx-a11y/control-has-associated-label
<button
type="button"
style={{ background: this.sourceAnchor?.followLinkEase === 'linear' ? '' : '#4476f7', borderRadius: 3 }}
@@ -1614,7 +1629,6 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
<div className="propertiesView-input inline">
<p>Capture Offset to Target</p>
{
- // eslint-disable-next-line jsx-a11y/control-has-associated-label
<button
type="button"
style={{ background: this.sourceAnchor?.followLinkXoffset === undefined ? '' : '#4476f7', borderRadius: 3 }}
@@ -1631,7 +1645,6 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
<div className="propertiesView-input inline">
<p>Center Target (no zoom)</p>
{
- // eslint-disable-next-line jsx-a11y/control-has-associated-label
<button
type="button"
style={{ background: this.sourceAnchor?.followLinkZoom ? '' : '#4476f7', borderRadius: 3 }}
@@ -1647,16 +1660,15 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
<div className="ribbon-property" style={{ display: !targZoom ? 'none' : 'inline-flex' }}>
<input className="presBox-input" style={{ width: '100%', color: SnappingManager.userColor, backgroundColor: SnappingManager.userBackgroundColor }} readOnly type="number" value={zoom} />
<div className="ribbon-propertyUpDown" style={{ display: 'flex', flexDirection: 'column' }}>
- <div className="ribbon-propertyUpDownItem" onClick={undoBatch(() => this.setZoom(String(zoom), 0.1))}>
+ <div className="ribbon-propertyUpDownItem" onClick={undoable(() => this.setZoom(String(zoom), 0.1), 'Zoom out')}>
<FontAwesomeIcon icon="caret-up" />
</div>
- <div className="ribbon-propertyUpDownItem" onClick={undoBatch(() => this.setZoom(String(zoom), -0.1))}>
+ <div className="ribbon-propertyUpDownItem" onClick={undoable(() => this.setZoom(String(zoom), -0.1), 'Zoom in')}>
<FontAwesomeIcon icon="caret-down" />
</div>
</div>
</div>
{
- // eslint-disable-next-line jsx-a11y/control-has-associated-label
<button
type="button"
style={{ background: !targZoom || this.sourceAnchor?.followLinkZoomScale === 0 ? '' : '#4476f7', borderRadius: 3, gridColumn: 3 }}
@@ -1746,8 +1758,8 @@ export class PropertiesView extends ObservableReactComponent<PropertiesViewProps
}
if (this.isPres && PresBox.Instance) {
const selectedItem: boolean = PresBox.Instance.selectedArray.size > 0;
- const type = [DocumentType.AUDIO, DocumentType.VID].includes(DocCast(PresBox.Instance.activeItem?.annotationOn)?.type as any as DocumentType)
- ? (DocCast(PresBox.Instance.activeItem?.annotationOn)?.type as any as DocumentType)
+ const type = [DocumentType.AUDIO, DocumentType.VID].includes(DocCast(PresBox.Instance.activeItem?.annotationOn)?.type as DocumentType)
+ ? (DocCast(PresBox.Instance.activeItem?.annotationOn)?.type as DocumentType)
: PresBox.targetRenderedDoc(PresBox.Instance.activeItem)?.type;
return (
<div className="propertiesView" style={{ width: this._props.width }}>
diff --git a/src/client/views/SidebarAnnos.tsx b/src/client/views/SidebarAnnos.tsx
index 9b70f1ca7..8f0a35df0 100644
--- a/src/client/views/SidebarAnnos.tsx
+++ b/src/client/views/SidebarAnnos.tsx
@@ -1,5 +1,3 @@
-/* eslint-disable jsx-a11y/no-static-element-interactions */
-/* eslint-disable jsx-a11y/click-events-have-key-events */
import { computed, makeObservable } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
@@ -40,7 +38,7 @@ interface ExtraProps {
}
@observer
export class SidebarAnnos extends ObservableReactComponent<FieldViewProps & ExtraProps> {
- constructor(props: any) {
+ constructor(props: FieldViewProps & ExtraProps) {
super(props);
makeObservable(this);
}
@@ -85,7 +83,7 @@ export class SidebarAnnos extends ObservableReactComponent<FieldViewProps & Extr
});
Doc.SetSelectOnLoad(target);
FormattedTextBox.DontSelectInitialText = true;
- const link = DocUtils.MakeLink(anchor, target, { link_relationship: 'inline comment:comment on' });
+ DocUtils.MakeLink(anchor, target, { link_relationship: 'inline comment:comment on' });
const taggedContent = this.childFilters()
.filter(data => data.split(':')[0])
@@ -102,7 +100,7 @@ export class SidebarAnnos extends ObservableReactComponent<FieldViewProps & Extr
});
if (!anchor.text) anchor[DocData].text = '-selection-';
- const textLines: any = [
+ const textLines: { type: string; attrs: object; content?: unknown[] }[] = [
{
type: 'paragraph',
attrs: { align: null, color: null, id: null, indent: null, inset: null, lineSpacing: null, paddingBottom: null, paddingTop: null },
@@ -222,7 +220,7 @@ export class SidebarAnnos extends ObservableReactComponent<FieldViewProps & Extr
pointerEvents: this._props.isContentActive() ? 'all' : undefined,
top: this._props.Document.type !== DocumentType.RTF && StrCast(this._props.Document._layout_showTitle) === 'title' ? 15 : 0,
right: 0,
- background: this._props.styleProvider?.(this._props.Document, this._props, StyleProp.WidgetColor),
+ background: this._props.styleProvider?.(this._props.Document, this._props, StyleProp.WidgetColor) as string,
width: `100%`,
height: '100%',
}}>
diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx
index b111904f3..2792955a0 100644
--- a/src/client/views/StyleProvider.tsx
+++ b/src/client/views/StyleProvider.tsx
@@ -17,7 +17,7 @@ import { emptyPath } from '../../Utils';
import { CollectionViewType, DocumentType } from '../documents/DocumentTypes';
import { IsFollowLinkScript } from '../documents/DocUtils';
import { SnappingManager } from '../util/SnappingManager';
-import { undoBatch, UndoManager } from '../util/UndoManager';
+import { undoable, UndoManager } from '../util/UndoManager';
import { TreeSort } from './collections/TreeSort';
import { Colors } from './global/globalEnums';
import { DocumentView, DocumentViewProps } from './nodes/DocumentView';
@@ -105,8 +105,8 @@ export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<FieldViewProps &
const fieldKey = fieldKeyProp ? fieldKeyProp + '_' : isCaption ? 'caption_' : '';
const isInk = () => layoutDoc?._layout_isSvg && !LayoutTemplateString;
const lockedPosition = () => doc && BoolCast(doc._lockedPosition);
- const titleHeight = () => styleProvider?.(doc, props, StyleProp.TitleHeight);
- const backgroundCol = () => styleProvider?.(doc, props, StyleProp.BackgroundColor + ':nonTransparent' + (isNonTransparentLevel + 1));
+ const titleHeight = () => styleProvider?.(doc, props, StyleProp.TitleHeight) as number;
+ const backgroundCol = () => styleProvider?.(doc, props, StyleProp.BackgroundColor + ':nonTransparent' + (isNonTransparentLevel + 1)) as string;
const color = () => styleProvider?.(doc, props, StyleProp.Color) as string;
const opacity = () => styleProvider?.(doc, props, StyleProp.Opacity);
const layoutShowTitle = () => styleProvider?.(doc, props, StyleProp.ShowTitle) as string;
@@ -383,11 +383,12 @@ export function DashboardToggleButton(doc: Doc, field: string, onIcon: IconProp,
size={Size.XSMALL}
color={color}
icon={<FontAwesomeIcon icon={doc[field] ? onIcon : offIcon} />}
- onClick={undoBatch(
+ onClick={undoable(
action((e: React.MouseEvent) => {
e.stopPropagation();
clickFunc ? clickFunc() : (doc[field] = doc[field] ? undefined : true);
- })
+ }),
+ 'toggle dashboard feature'
)}
/>
);
diff --git a/src/client/views/TemplateMenu.tsx b/src/client/views/TemplateMenu.tsx
index cff32a557..e0d0de165 100644
--- a/src/client/views/TemplateMenu.tsx
+++ b/src/client/views/TemplateMenu.tsx
@@ -48,7 +48,8 @@ export class TemplateMenu extends React.Component<TemplateMenuProps> {
.forEach(key => runInAction(() => this._addedKeys.add(key.replace('layout_', '')))); // prettier-ignore
}
@computed get scriptField() {
- const script = ScriptField.MakeScript('docs.map(d => switchView(d, this))', { this: Doc.name }, { docs: this.props.docViews.map(dv => dv.Document) as any });
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ const script = ScriptField.MakeScript('docs.map(d => switchView(d, this))', { this: Doc.name }, { docs: this.props.docViews.map(dv => dv.Document) as any }); // allow a captured variable for Doc[] since this script isn't being saved to a Doc
return script ? () => script : undefined;
}
diff --git a/src/client/views/UndoStack.tsx b/src/client/views/UndoStack.tsx
index 2d461c0ab..9b71d46ea 100644
--- a/src/client/views/UndoStack.tsx
+++ b/src/client/views/UndoStack.tsx
@@ -1,5 +1,3 @@
-/* eslint-disable jsx-a11y/no-static-element-interactions */
-/* eslint-disable jsx-a11y/click-events-have-key-events */
import { Tooltip } from '@mui/material';
import { Popup, Type } from 'browndash-components';
import { observer } from 'mobx-react';
diff --git a/src/client/views/collections/CollectionCarouselView.tsx b/src/client/views/collections/CollectionCarouselView.tsx
index c969c39e5..4bec2d963 100644
--- a/src/client/views/collections/CollectionCarouselView.tsx
+++ b/src/client/views/collections/CollectionCarouselView.tsx
@@ -10,7 +10,6 @@ import { DocCast, NumCast, ScriptCast, StrCast } from '../../../fields/Types';
import { DocumentType } from '../../documents/DocumentTypes';
import { DragManager } from '../../util/DragManager';
import { ContextMenu } from '../ContextMenu';
-import { ContextMenuProps } from '../ContextMenuItem';
import { StyleProp } from '../StyleProp';
import { DocumentView } from '../nodes/DocumentView';
import { FieldViewProps } from '../nodes/FieldView';
@@ -135,7 +134,7 @@ export class CollectionCarouselView extends CollectionSubView() {
const cm = ContextMenu.Instance;
const revealOptions = cm.findByDescription('Filter Flashcards');
- const revealItems: ContextMenuProps[] = revealOptions && 'subitems' in revealOptions ? revealOptions.subitems : [];
+ const revealItems = revealOptions?.subitems ?? [];
revealItems.push({description: 'All', event: () => {this.layoutDoc.filterOp = undefined;}, icon: 'layer-group',}); // prettier-ignore
revealItems.push({description: 'Star', event: () => {this.layoutDoc.filterOp = cardMode.STAR;}, icon: 'star',}); // prettier-ignore
revealItems.push({description: 'Practice Mode', event: () => {this.layoutDoc.filterOp = cardMode.PRACTICE;}, icon: 'check',}); // prettier-ignore
diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx
index 7b9475590..f1b5e4db2 100644
--- a/src/client/views/collections/CollectionMenu.tsx
+++ b/src/client/views/collections/CollectionMenu.tsx
@@ -19,7 +19,7 @@ import { DragManager } from '../../util/DragManager';
import { dropActionType } from '../../util/DropActionTypes';
import { SnappingManager } from '../../util/SnappingManager';
import { Transform } from '../../util/Transform';
-import { undoBatch } from '../../util/UndoManager';
+import { undoBatch, undoable } from '../../util/UndoManager';
import { AntimodeMenu } from '../AntimodeMenu';
import { EditableView } from '../EditableView';
import { DefaultStyleProvider, returnEmptyDocViewList } from '../StyleProvider';
@@ -181,7 +181,7 @@ export class CollectionViewBaseChrome extends React.Component<CollectionViewMenu
params: ['target', 'source'],
title: 'item view',
script: 'this.target.childLayoutTemplate = getDocTemplate(this.source?.[0])',
- immediate: undoBatch((source: Doc[]) => {
+ immediate: undoable((source: Doc[]) => {
let formatStr = source.length && Cast(source[0].text, RichTextField, null)?.Text;
try {
formatStr && JSON.parse(formatStr);
@@ -196,25 +196,25 @@ export class CollectionViewBaseChrome extends React.Component<CollectionViewMenu
Doc.SetInPlace(this.target, 'childLayoutString', undefined, true);
Doc.SetInPlace(this.target, 'childLayoutTemplate', undefined, true);
}
- }),
+ }, ''),
initialize: emptyFunction,
};
_narrativeCommand = {
params: ['target', 'source'],
title: 'child click view',
script: 'this.target.childClickedOpenTemplateView = getDocTemplate(this.source?.[0])',
- immediate: undoBatch((source: Doc[]) => {
+ immediate: undoable((source: Doc[]) => {
source.length && (this.target.childClickedOpenTemplateView = Doc.getDocTemplate(source?.[0]));
- }),
+ }, 'narrative command'),
initialize: emptyFunction,
};
_contentCommand = {
params: ['target', 'source'],
title: 'set content',
script: 'getProto(this.target).data = copyField(this.source);',
- immediate: undoBatch((source: Doc[]) => {
+ immediate: undoable((source: Doc[]) => {
this.target[DocData].data = new List<Doc>(source);
- }),
+ }, ''),
initialize: emptyFunction,
};
_onClickCommand = {
@@ -225,19 +225,19 @@ export class CollectionViewBaseChrome extends React.Component<CollectionViewMenu
getProto(this.proxy[0]).target = this.target.target;
getProto(this.proxy[0]).source = copyField(this.target.source);
}}`,
- immediate: undoBatch(() => {}),
+ immediate: undoable(() => {}, ''),
initialize: emptyFunction,
};
_viewCommand = {
params: ['target'],
title: 'bookmark view',
script: "this.target._freeform_panX = this.target_freeform_panX; this.target._freeform_panY = this['target-freeform_panY']; this.target._freeform_scale = this['target_freeform_scale']; gotoFrame(this.target, this['target-currentFrame']);",
- immediate: undoBatch(() => {
+ immediate: undoable(() => {
this.target._freeform_panX = 0;
this.target._freeform_panY = 0;
this.target._freeform_scale = 1;
this.target._currentFrame = this.target._currentFrame === undefined ? undefined : 0;
- }),
+ }, ''),
initialize: (button: Doc) => {
button['target-panX'] = this.target._freeform_panX;
button['target-panY'] = this.target._freeform_panY;
@@ -249,18 +249,18 @@ export class CollectionViewBaseChrome extends React.Component<CollectionViewMenu
params: ['target'],
title: 'fit content',
script: 'this.target._freeform_fitContentsToBox = !this.target._freeform_fitContentsToBox;',
- immediate: undoBatch(() => {
+ immediate: undoable(() => {
this.target._freeform_fitContentsToBox = !this.target._freeform_fitContentsToBox;
- }),
+ }, ''),
initialize: emptyFunction,
};
_fitContentCommand = {
params: ['target'],
title: 'toggle clusters',
script: 'this.target._freeform_useClusters = !this.target._freeform_useClusters;',
- immediate: undoBatch(() => {
+ immediate: undoable(() => {
this.target._freeform_useClusters = !this.target._freeform_useClusters;
- }),
+ }, ''),
initialize: emptyFunction,
};
_saveFilterCommand = {
@@ -268,10 +268,10 @@ export class CollectionViewBaseChrome extends React.Component<CollectionViewMenu
title: 'save filter',
script: `this.target._childFilters = compareLists(this.target_childFilters,this.target._childFilters) ? undefined : copyField(this.target_childFilters);
this.target._searchFilterDocs = compareLists(this.target_searchFilterDocs,this.target._searchFilterDocs) ? undefined: copyField(this.target_searchFilterDocs);`,
- immediate: undoBatch(() => {
+ immediate: undoable(() => {
this.target._childFilters = undefined;
this.target._searchFilterDocs = undefined;
- }),
+ }, ''),
initialize: (button: Doc) => {
const activeDash = Doc.ActiveDashboard;
if (activeDash) {
@@ -594,9 +594,9 @@ export class CollectionGridViewChrome extends React.Component<CollectionViewMenu
*/
onNumColsChange = (e: React.ChangeEvent<HTMLInputElement>) => {
if (e.currentTarget.valueAsNumber > 0)
- undoBatch(() => {
+ undoable(() => {
this.document.gridNumCols = e.currentTarget.valueAsNumber;
- })();
+ }, '')();
};
/**
@@ -625,9 +625,9 @@ export class CollectionGridViewChrome extends React.Component<CollectionViewMenu
onIncrementButtonClick = () => {
this.clicked = true;
this.entered && (this.document.gridNumCols as number)--;
- undoBatch(() => {
+ undoable(() => {
this.document.gridNumCols = this.numCols + 1;
- })();
+ }, '')();
this.entered = false;
};
@@ -638,9 +638,9 @@ export class CollectionGridViewChrome extends React.Component<CollectionViewMenu
this.clicked = true;
if (this.numCols > 1 && !this.decrementLimitReached) {
this.entered && (this.document.gridNumCols as number)++;
- undoBatch(() => {
+ undoable(() => {
this.document.gridNumCols = this.numCols - 1;
- })();
+ }, '')();
if (this.numCols === 1) this.decrementLimitReached = true;
}
this.entered = false;
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index ff316cfbd..0557a9102 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -213,7 +213,7 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
ContextMenu.Instance.addItem({ description: 'Options...', subitems: layoutItems, icon: 'eye' });
if (!Doc.noviceMode) {
const existingOnClick = ContextMenu.Instance.findByDescription('OnClick...');
- const onClicks: ContextMenuProps[] = existingOnClick.subitems ?? [];
+ const onClicks: ContextMenuProps[] = existingOnClick?.subitems ?? [];
onClicks.push({ description: 'Edit onChecked Script', event: () => UndoManager.RunInBatch(() => DocUtils.makeCustomViewClicked(this.Document, undefined, 'onCheckedClick'), 'edit onCheckedClick'), icon: 'edit' });
!existingOnClick && ContextMenu.Instance.addItem({ description: 'OnClick...', noexpand: true, subitems: onClicks, icon: 'mouse-pointer' });
}
@@ -226,7 +226,7 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
get editableTitle() {
return (
<EditableView
- contents={this.dataDoc.title}
+ contents={StrCast(this.dataDoc.title)}
display="block"
maxHeight={72}
height="auto"
diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx
index 5c304b4a9..c9ab5f661 100644
--- a/src/client/views/collections/CollectionView.tsx
+++ b/src/client/views/collections/CollectionView.tsx
@@ -48,7 +48,7 @@ export class CollectionView extends ViewBoxAnnotatableComponent<CollectionViewPr
private reactionDisposer: IReactionDisposer | undefined;
@observable _isContentActive: boolean | undefined = undefined;
- constructor(props: any) {
+ constructor(props: CollectionViewProps) {
super(props);
makeObservable(this);
this._annotationKeySuffix = returnEmptyString;
@@ -72,7 +72,7 @@ export class CollectionView extends ViewBoxAnnotatableComponent<CollectionViewPr
}
get collectionViewType(): CollectionViewType | undefined {
- const viewField = StrCast(this.layoutDoc._type_collection) as any as CollectionViewType;
+ const viewField = StrCast(this.layoutDoc._type_collection) as CollectionViewType;
if (CollectionView._safeMode) {
switch (viewField) {
case CollectionViewType.Freeform:
@@ -132,7 +132,7 @@ export class CollectionView extends ViewBoxAnnotatableComponent<CollectionViewPr
];
const existingVm = ContextMenu.Instance.findByDescription(category);
- const catItems = existingVm && 'subitems' in existingVm ? existingVm.subitems : [];
+ const catItems = existingVm?.subitems ?? [];
catItems.push({ description: 'Add a Perspective...', addDivider: true, noexpand: true, subitems: subItems, icon: 'eye' });
!existingVm && ContextMenu.Instance.addItem({ description: category, subitems: catItems, icon: 'eye' });
}
@@ -151,7 +151,7 @@ export class CollectionView extends ViewBoxAnnotatableComponent<CollectionViewPr
});
const options = cm.findByDescription('Options...');
- const optionItems = options && 'subitems' in options ? options.subitems : [];
+ const optionItems = options?.subitems ?? [];
!Doc.noviceMode ? optionItems.splice(0, 0, { description: `${this.Document.forceActive ? 'Select' : 'Force'} Contents Active`, event: () => {this.Document.forceActive = !this.Document.forceActive}, icon: 'project-diagram' }) : null; // prettier-ignore
if (this.Document.childLayout instanceof Doc) {
optionItems.push({ description: 'View Child Layout', event: () => this._props.addDocTab(this.Document.childLayout as Doc, OpenWhere.addRight), icon: 'project-diagram' });
@@ -165,7 +165,7 @@ export class CollectionView extends ViewBoxAnnotatableComponent<CollectionViewPr
if (!Doc.noviceMode && !this.Document.annotationOn && !this._props.hideClickBehaviors) {
const existingOnClick = cm.findByDescription('OnClick...');
- const onClicks = existingOnClick && 'subitems' in existingOnClick ? existingOnClick.subitems : [];
+ const onClicks = existingOnClick?.subitems ?? [];
const funcs = [
{ key: 'onChildClick', name: 'On Child Clicked' },
{ key: 'onChildDoubleClick', name: 'On Child Double Clicked' },
@@ -195,7 +195,7 @@ export class CollectionView extends ViewBoxAnnotatableComponent<CollectionViewPr
if (!Doc.noviceMode) {
const more = cm.findByDescription('More...');
- const moreItems = more && 'subitems' in more ? more.subitems : [];
+ const moreItems = more?.subitems ?? [];
moreItems.push({ description: 'Export Image Hierarchy', icon: 'columns', event: () => ImageUtils.ExportHierarchyToFileSystem(this.Document) });
!more && cm.addItem({ description: 'More...', subitems: moreItems, icon: 'hand-point-right' });
}
diff --git a/src/client/views/global/globalScripts.ts b/src/client/views/global/globalScripts.ts
index 2b7de5082..2c7920bdd 100644
--- a/src/client/views/global/globalScripts.ts
+++ b/src/client/views/global/globalScripts.ts
@@ -1,7 +1,8 @@
+/* eslint-disable @typescript-eslint/no-unused-vars */
import { Colors } from 'browndash-components';
import { action, runInAction } from 'mobx';
import { aggregateBounds } from '../../../Utils';
-import { Doc, DocListCast, NumListCast, Opt } from '../../../fields/Doc';
+import { Doc, DocListCast, FieldType, NumListCast, Opt } from '../../../fields/Doc';
import { DocData } from '../../../fields/DocSymbols';
import { InkTool } from '../../../fields/InkField';
import { List } from '../../../fields/List';
@@ -138,7 +139,7 @@ ScriptingGlobals.add(function showFreeform(attr: 'center' | 'grid' | 'snaplines'
const map: Map<'flashcards' | 'center' | 'grid' | 'snaplines' | 'clusters' | 'arrange' | 'viewAll' | 'fitOnce' | 'time' | 'docType' | 'color' | 'links' | 'like' | 'star' | 'idea' | 'chat' | '1' | '2' | '3' | '4',
{
waitForRender?: boolean;
- checkResult: (doc: Doc) => any;
+ checkResult: (doc: Doc) => boolean;
setDoc: (doc: Doc, dv: DocumentView) => void;
}> = new Map([
['grid', {
@@ -220,6 +221,7 @@ ScriptingGlobals.add(function showFreeform(attr: 'center' | 'grid' | 'snaplines'
}],
]);
for (let i = 0; i < 8; i++) {
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
map.set((i + 1 + '') as any, {
checkResult: (doc: Doc) => NumListCast(doc?.cardSort_visibleSortGroups).includes(i),
setDoc: (doc: Doc, dv: DocumentView) => {
@@ -278,25 +280,25 @@ ScriptingGlobals.add(function cardHasLabel(label: string) {
// });
// eslint-disable-next-line prefer-arrow-callback
-ScriptingGlobals.add(function setFontAttr(attr: 'font' | 'fontColor' | 'highlight' | 'fontSize' | 'alignment', value: any, checkResult?: boolean) {
+ScriptingGlobals.add(function setFontAttr(attr: 'font' | 'fontColor' | 'highlight' | 'fontSize' | 'alignment', value: string | number, checkResult?: boolean) {
const editorView = RichTextMenu.Instance?.TextView?.EditorView;
// prettier-ignore
- const map: Map<'font'|'fontColor'|'highlight'|'fontSize'|'alignment', { checkResult: () => any; setDoc: () => void;}> = new Map([
+ const map: Map<'font'|'fontColor'|'highlight'|'fontSize'|'alignment', { checkResult: () => string | undefined; setDoc: () => void;}> = new Map([
['font', {
checkResult: () => RichTextMenu.Instance?.fontFamily,
- setDoc: () => value && RichTextMenu.Instance?.setFontField(value, 'fontFamily'),
+ setDoc: () => value && RichTextMenu.Instance?.setFontField(value.toString(), 'fontFamily'),
}],
['highlight', {
checkResult: () => RichTextMenu.Instance?.fontHighlight,
- setDoc: () => value && RichTextMenu.Instance?.setFontField(value, 'fontHighlight'),
+ setDoc: () => value && RichTextMenu.Instance?.setFontField(value.toString(), 'fontHighlight'),
}],
['fontColor', {
checkResult: () => RichTextMenu.Instance?.fontColor,
- setDoc: () => value && RichTextMenu.Instance?.setFontField(value, 'fontColor'),
+ setDoc: () => value && RichTextMenu.Instance?.setFontField(value.toString(), 'fontColor'),
}],
['alignment', {
checkResult: () => RichTextMenu.Instance?.textAlign,
- setDoc: () => { value && editorView?.state ? RichTextMenu.Instance?.align(editorView, editorView.dispatch, value):(Doc.UserDoc().textAlign = value); },
+ setDoc: () => { value && editorView?.state ? RichTextMenu.Instance?.align(editorView, editorView.dispatch, value.toString() as "center"|"left"|"right"):(Doc.UserDoc().textAlign = value); },
}],
['fontSize', {
checkResult: () => RichTextMenu.Instance?.fontSize.replace('px', ''),
@@ -317,7 +319,7 @@ ScriptingGlobals.add(function setFontAttr(attr: 'font' | 'fontColor' | 'highligh
});
type attrname = 'noAutoLink' | 'dictation' | 'bold' | 'italics' | 'elide' | 'underline' | 'left' | 'center' | 'right' | 'vcent' | 'bullet' | 'decimal';
-type attrfuncs = [attrname, { checkResult: () => boolean; toggle?: () => any }];
+type attrfuncs = [attrname, { checkResult: () => boolean; toggle?: () => unknown }];
// eslint-disable-next-line prefer-arrow-callback
ScriptingGlobals.add(function toggleCharStyle(charStyle: attrname, checkResult?: boolean) {
@@ -438,7 +440,7 @@ function setActiveTool(tool: InkTool | Gestures, keepPrim: boolean, checkResult?
if (GestureOverlay.Instance) {
GestureOverlay.Instance.KeepPrimitiveMode = keepPrim;
}
- if (Object.values(Gestures).includes(tool as any)) {
+ if (Object.values(Gestures).includes(tool as Gestures)) {
if (GestureOverlay.Instance.InkShape === tool && !keepPrim) {
Doc.ActiveTool = InkTool.None;
GestureOverlay.Instance.InkShape = undefined;
@@ -450,14 +452,14 @@ function setActiveTool(tool: InkTool | Gestures, keepPrim: boolean, checkResult?
if (Doc.UserDoc().ActiveTool === tool) {
Doc.ActiveTool = InkTool.None;
} else {
- if ([InkTool.StrokeEraser, InkTool.RadiusEraser, InkTool.SegmentEraser].includes(tool as any)) {
+ if ([InkTool.StrokeEraser, InkTool.RadiusEraser, InkTool.SegmentEraser].includes(tool as InkTool)) {
Doc.UserDoc().activeEraserTool = tool;
}
// pen or eraser
if (Doc.ActiveTool === tool && !GestureOverlay.Instance.InkShape && !keepPrim) {
Doc.ActiveTool = InkTool.None;
} else {
- Doc.ActiveTool = tool as any;
+ Doc.ActiveTool = tool as InkTool;
GestureOverlay.Instance.InkShape = undefined;
}
}
@@ -476,10 +478,10 @@ ScriptingGlobals.add(function activeEraserTool() {
// toggle: Set overlay status of selected document
// eslint-disable-next-line prefer-arrow-callback
-ScriptingGlobals.add(function setInkProperty(option: 'inkMask' | 'labels' | 'fillColor' | 'strokeWidth' | 'strokeColor' | 'eraserWidth', value: any, checkResult?: boolean) {
+ScriptingGlobals.add(function setInkProperty(option: 'inkMask' | 'labels' | 'fillColor' | 'strokeWidth' | 'strokeColor' | 'eraserWidth', value: string | number, checkResult?: boolean) {
const selected = DocumentView.SelectedDocs().lastElement() ?? Doc.UserDoc();
// prettier-ignore
- const map: Map<'inkMask' | 'labels' | 'fillColor' | 'strokeWidth' | 'strokeColor' | 'eraserWidth', { checkResult: () => any; setInk: (doc: Doc) => void; setMode: () => void }> = new Map([
+ const map: Map<'inkMask' | 'labels' | 'fillColor' | 'strokeWidth' | 'strokeColor' | 'eraserWidth', { checkResult: () => number|boolean|string|undefined; setInk: (doc: Doc) => void; setMode: () => void }> = new Map([
['inkMask', {
checkResult: () => ((selected?._layout_isSvg ? BoolCast(selected[DocData].stroke_isInkMask) : ActiveIsInkMask())),
setInk: (doc: Doc) => { doc[DocData].stroke_isInkMask = !doc.stroke_isInkMask; },
@@ -508,7 +510,7 @@ ScriptingGlobals.add(function setInkProperty(option: 'inkMask' | 'labels' | 'fil
[ 'eraserWidth', {
checkResult: () => ActiveEraserWidth(),
setInk: (doc: Doc) => { },
- setMode: () => { SetEraserWidth(value.toString());},
+ setMode: () => { SetEraserWidth(+value);},
}]
]);
diff --git a/src/client/views/linking/LinkMenu.tsx b/src/client/views/linking/LinkMenu.tsx
index 12b83414c..b38213e08 100644
--- a/src/client/views/linking/LinkMenu.tsx
+++ b/src/client/views/linking/LinkMenu.tsx
@@ -24,7 +24,7 @@ interface Props {
export class LinkMenu extends ObservableReactComponent<Props> {
_editorRef = React.createRef<HTMLDivElement>();
@observable _linkMenuRef = React.createRef<HTMLDivElement>();
- constructor(props: any) {
+ constructor(props: Props) {
super(props);
makeObservable(this);
}
@@ -40,7 +40,7 @@ export class LinkMenu extends ObservableReactComponent<Props> {
onPointerDown = action((e: PointerEvent) => {
LinkInfo.Clear();
- if (!this._linkMenuRef.current?.contains(e.target as any) && !this._editorRef.current?.contains(e.target as any)) {
+ if (!this._linkMenuRef.current?.contains(e.target as HTMLElement) && !this._editorRef.current?.contains(e.target as HTMLElement)) {
this.clear();
}
});
diff --git a/src/client/views/linking/LinkMenuGroup.tsx b/src/client/views/linking/LinkMenuGroup.tsx
index cd735318e..c15508669 100644
--- a/src/client/views/linking/LinkMenuGroup.tsx
+++ b/src/client/views/linking/LinkMenuGroup.tsx
@@ -1,5 +1,3 @@
-/* eslint-disable jsx-a11y/no-static-element-interactions */
-/* eslint-disable jsx-a11y/click-events-have-key-events */
/* eslint-disable react/require-default-props */
import { action, observable } from 'mobx';
import { observer } from 'mobx-react';
diff --git a/src/client/views/linking/LinkMenuItem.tsx b/src/client/views/linking/LinkMenuItem.tsx
index 9ce04ffac..f54d8311d 100644
--- a/src/client/views/linking/LinkMenuItem.tsx
+++ b/src/client/views/linking/LinkMenuItem.tsx
@@ -1,5 +1,3 @@
-/* eslint-disable jsx-a11y/no-static-element-interactions */
-/* eslint-disable jsx-a11y/click-events-have-key-events */
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { Tooltip } from '@mui/material';
import { action, computed, makeObservable, observable } from 'mobx';
@@ -15,7 +13,7 @@ import { DragManager } from '../../util/DragManager';
import { dropActionType } from '../../util/DropActionTypes';
import { LinkManager } from '../../util/LinkManager';
import { SnappingManager } from '../../util/SnappingManager';
-import { undoBatch } from '../../util/UndoManager';
+import { undoable } from '../../util/UndoManager';
import { ObservableReactComponent } from '../ObservableReactComponent';
import { DocumentView, DocumentViewInternal } from '../nodes/DocumentView';
import { LinkInfo } from '../nodes/LinkDocPreview';
@@ -56,7 +54,7 @@ export async function StartLinkTargetsDrag(dragEle: HTMLElement, docView: Docume
export class LinkMenuItem extends ObservableReactComponent<LinkMenuItemProps> {
private _drag = React.createRef<HTMLDivElement>();
_editRef = React.createRef<HTMLDivElement>();
- constructor(props: any) {
+ constructor(props: LinkMenuItemProps) {
super(props);
makeObservable(this);
}
@@ -123,7 +121,7 @@ export class LinkMenuItem extends ObservableReactComponent<LinkMenuItemProps> {
this,
e,
moveEv => {
- const eleClone: any = this._drag.current?.cloneNode(true);
+ const eleClone = this._drag.current?.cloneNode(true) as HTMLElement;
if (eleClone) {
eleClone.style.transform = `translate(${moveEv.x}px, ${moveEv.y}px)`;
StartLinkTargetsDrag(eleClone, this._props.docView, moveEv.x, moveEv.y, this._props.sourceDoc, [this._props.linkDoc]);
@@ -151,7 +149,17 @@ export class LinkMenuItem extends ObservableReactComponent<LinkMenuItemProps> {
);
};
- deleteLink = (e: React.PointerEvent): void => setupMoveUpEvents(this, e, returnFalse, emptyFunction, undoBatch(action(() => Doc.DeleteLink?.(this._props.linkDoc))));
+ deleteLink = (e: React.PointerEvent): void =>
+ setupMoveUpEvents(
+ this,
+ e,
+ returnFalse,
+ emptyFunction,
+ undoable(
+ action(() => Doc.DeleteLink?.(this._props.linkDoc)),
+ 'delete link'
+ )
+ );
@observable _hover = false;
docView = () => this._props.docView;
render() {
diff --git a/src/client/views/nodes/DataVizBox/DataVizBox.tsx b/src/client/views/nodes/DataVizBox/DataVizBox.tsx
index 69277b054..df6e74d85 100644
--- a/src/client/views/nodes/DataVizBox/DataVizBox.tsx
+++ b/src/client/views/nodes/DataVizBox/DataVizBox.tsx
@@ -429,7 +429,7 @@ export class DataVizBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
specificContextMenu = (): void => {
const cm = ContextMenu.Instance;
const options = cm.findByDescription('Options...');
- const optionItems = options && 'subitems' in options ? options.subitems : [];
+ const optionItems = options?.subitems ?? [];
optionItems.push({ description: `Analyze with AI`, event: () => this.askGPT(), icon: 'lightbulb' });
!options && cm.addItem({ description: 'Options...', subitems: optionItems, icon: 'eye' });
};
diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx
index 8a2c4e530..b178d6554 100644
--- a/src/client/views/nodes/DocumentContentsView.tsx
+++ b/src/client/views/nodes/DocumentContentsView.tsx
@@ -89,8 +89,8 @@ export class DocumentContentsView extends ObservableReactComponent<DocumentConte
/**
* Set of all available rendering componets for Docs (e.g., ImageBox, CollectionFreeFormView, etc)
*/
- private static Components: { [key: string]: DocumentContentsViewProps };
- public static Init(defaultLayoutString: string, components: { [key: string]: DocumentContentsViewProps }) {
+ private static Components: { [key: string]: unknown };
+ public static Init(defaultLayoutString: string, components: { [key: string]: unknown }) {
DocumentContentsView.DefaultLayoutString = defaultLayoutString;
DocumentContentsView.Components = components;
}
diff --git a/src/client/views/nodes/FunctionPlotBox.tsx b/src/client/views/nodes/FunctionPlotBox.tsx
index 3d1bd7563..6b439cd64 100644
--- a/src/client/views/nodes/FunctionPlotBox.tsx
+++ b/src/client/views/nodes/FunctionPlotBox.tsx
@@ -1,4 +1,4 @@
-import functionPlot from 'function-plot';
+import functionPlot, { Chart } from 'function-plot';
import { computed, makeObservable, reaction } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
@@ -22,11 +22,11 @@ export class FunctionPlotBox extends ViewBoxAnnotatableComponent<FieldViewProps>
return FieldView.LayoutString(FunctionPlotBox, fieldKey);
}
public static GraphCount = 0;
- _plot: any;
+ _plot: Chart | undefined;
_plotId = '';
- _plotEle: any;
+ _plotEle: HTMLDivElement | null = null;
- constructor(props: any) {
+ constructor(props: FieldViewProps) {
super(props);
makeObservable(this);
this._plotId = 'graph' + FunctionPlotBox.GraphCount++;
@@ -42,8 +42,10 @@ export class FunctionPlotBox extends ViewBoxAnnotatableComponent<FieldViewProps>
getAnchor = (addAsAnnotation: boolean, pinProps?: PinProps) => {
const anchor = Docs.Create.ConfigDocument({ annotationOn: this.Document });
PinDocView(anchor, { pinDocLayout: pinProps?.pinDocLayout, pinData: { ...(pinProps?.pinData ?? {}), datarange: true } }, this.Document);
- anchor.config_xRange = new List<number>(Array.from(this._plot.options.xAxis.domain));
- anchor.config_yRange = new List<number>(Array.from(this._plot.options.yAxis.domain));
+ if (this._plot) {
+ anchor.config_xRange = new List<number>(Array.from(this._plot.options.xAxis?.domain ?? []));
+ anchor.config_yRange = new List<number>(Array.from(this._plot.options.yAxis?.domain ?? []));
+ }
if (addAsAnnotation) this.addDocument(anchor);
return anchor;
};
@@ -68,9 +70,9 @@ export class FunctionPlotBox extends ViewBoxAnnotatableComponent<FieldViewProps>
const width = this._props.PanelWidth();
const height = this._props.PanelHeight();
try {
- this._plotEle.children.length && this._plotEle.removeChild(this._plotEle.children[0]);
+ this._plotEle?.children.length && this._plotEle.removeChild(this._plotEle.children[0]);
this._plot = functionPlot({
- target: '#' + this._plotEle.id,
+ target: '#' + this._plotEle?.id,
width,
height,
xAxis: { domain: Cast(this.layoutDoc.xRange, listSpec('number'), [-10, 10]) },
@@ -104,7 +106,7 @@ export class FunctionPlotBox extends ViewBoxAnnotatableComponent<FieldViewProps>
return false;
};
- _dropDisposer: any;
+ _dropDisposer: DragManager.DragDropDisposer | undefined;
protected createDropTarget = (ele: HTMLDivElement) => {
this._dropDisposer?.();
if (ele) {
diff --git a/src/client/views/nodes/KeyValueBox.tsx b/src/client/views/nodes/KeyValueBox.tsx
index 9e77e0973..95e344004 100644
--- a/src/client/views/nodes/KeyValueBox.tsx
+++ b/src/client/views/nodes/KeyValueBox.tsx
@@ -14,7 +14,6 @@ import { SetupDrag } from '../../util/DragManager';
import { CompiledScript } from '../../util/Scripting';
import { undoable } from '../../util/UndoManager';
import { ContextMenu } from '../ContextMenu';
-import { ContextMenuProps } from '../ContextMenuItem';
import { ViewBoxBaseComponent } from '../DocComponent';
import { DocumentIconContainer } from './DocumentIcon';
import { FieldView, FieldViewProps } from './FieldView';
@@ -296,7 +295,7 @@ export class KeyValueBox extends ViewBoxBaseComponent<FieldViewProps>() {
specificContextMenu = (): void => {
const cm = ContextMenu.Instance;
const open = cm.findByDescription('Change Perspective...');
- const openItems: ContextMenuProps[] = open && 'subitems' in open ? open.subitems : [];
+ const openItems = open?.subitems ?? [];
openItems.push({
description: 'Default Perspective',
event: () => {
diff --git a/src/client/views/nodes/KeyValuePair.tsx b/src/client/views/nodes/KeyValuePair.tsx
index 3023716b1..8e74e1ca2 100644
--- a/src/client/views/nodes/KeyValuePair.tsx
+++ b/src/client/views/nodes/KeyValuePair.tsx
@@ -110,7 +110,7 @@ export class KeyValuePair extends ObservableReactComponent<KeyValuePairProps> {
<td className="keyValuePair-td-value" style={{ width: `${100 - this._props.keyWidth}%` }} onContextMenu={this.onContextMenu}>
<div className="keyValuePair-td-value-container">
<EditableView
- contents={undefined}
+ contents={''}
fieldContents={{
Document: this._props.doc,
childFilters: returnEmptyFilter,
diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx
index c03694dd9..b17275a1e 100644
--- a/src/client/views/nodes/PDFBox.tsx
+++ b/src/client/views/nodes/PDFBox.tsx
@@ -22,7 +22,6 @@ import { undoBatch, UndoManager } from '../../util/UndoManager';
import { CollectionFreeFormView } from '../collections/collectionFreeForm';
import { CollectionStackingView } from '../collections/CollectionStackingView';
import { ContextMenu } from '../ContextMenu';
-import { ContextMenuProps } from '../ContextMenuItem';
import { ViewBoxAnnotatableComponent } from '../DocComponent';
import { Colors } from '../global/globalEnums';
import { PDFViewer } from '../pdf/PDFViewer';
@@ -398,6 +397,7 @@ export class PDFBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
</button>
</>
);
+
const searchTitle = `${!this._searching ? 'Open' : 'Close'} Search Bar`;
const curPage = NumCast(this.Document._layout_curPage) || 1;
return !this._props.isContentActive() || this._pdfViewer?.isAnnotating ? null : (
@@ -473,14 +473,14 @@ export class PDFBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
specificContextMenu = (): void => {
const cm = ContextMenu.Instance;
const options = cm.findByDescription('Options...');
- const optionItems: ContextMenuProps[] = options && 'subitems' in options ? options.subitems : [];
+ const optionItems = options?.subitems ?? [];
!Doc.noviceMode && optionItems.push({ description: 'Toggle Sidebar Type', event: this.toggleSidebarType, icon: 'expand-arrows-alt' });
!Doc.noviceMode && optionItems.push({ description: 'update icon', event: () => this.pdfUrl && this.updateIcon(), icon: 'expand-arrows-alt' });
// optionItems.push({ description: "Toggle Sidebar ", event: () => this.toggleSidebar(), icon: "expand-arrows-alt" });
!options && ContextMenu.Instance.addItem({ description: 'Options...', subitems: optionItems, icon: 'asterisk' });
const help = cm.findByDescription('Help...');
- const helpItems: ContextMenuProps[] = help && 'subitems' in help ? help.subitems : [];
+ const helpItems = help?.subitems ?? [];
helpItems.push({ description: 'Copy path', event: () => this.pdfUrl && ClientUtils.CopyText(ClientUtils.prepend('') + this.pdfUrl.url.pathname), icon: 'expand-arrows-alt' });
!help && ContextMenu.Instance.addItem({ description: 'Help...', noexpand: true, subitems: helpItems, icon: 'asterisk' });
};
diff --git a/src/client/views/nodes/formattedText/EquationView.tsx b/src/client/views/nodes/formattedText/EquationView.tsx
index 4d0e9efee..df1421a33 100644
--- a/src/client/views/nodes/formattedText/EquationView.tsx
+++ b/src/client/views/nodes/formattedText/EquationView.tsx
@@ -17,7 +17,7 @@ interface IEquationViewInternal {
tbox: FormattedTextBox;
width: number;
height: number;
- getPos: () => number;
+ getPos: () => number | undefined;
setEditor: (editor: EquationEditor | undefined) => void;
}
@@ -47,7 +47,7 @@ export class EquationViewInternal extends React.Component<IEquationViewInternal>
className="equationView"
onKeyDown={e => {
if (e.key === 'Enter') {
- this.props.tbox.EditorView!.dispatch(this.props.tbox.EditorView!.state.tr.setSelection(new TextSelection(this.props.tbox.EditorView!.state.doc.resolve(this.props.getPos() + 1))));
+ this.props.tbox.EditorView!.dispatch(this.props.tbox.EditorView!.state.tr.setSelection(new TextSelection(this.props.tbox.EditorView!.state.doc.resolve((this.props.getPos() ?? 0) + 1))));
this.props.tbox.EditorView!.focus();
e.preventDefault();
}
@@ -82,8 +82,8 @@ export class EquationView {
tbox: FormattedTextBox;
view: EditorView;
_editor: EquationEditor | undefined;
- getPos: () => number;
- constructor(node: Node, view: EditorView, getPos: () => number, tbox: FormattedTextBox) {
+ getPos: () => number | undefined;
+ constructor(node: Node, view: EditorView, getPos: () => number | undefined, tbox: FormattedTextBox) {
this.tbox = tbox;
this.view = view;
this.getPos = getPos;
@@ -109,7 +109,7 @@ export class EquationView {
this._editor?.mathField.focus();
}
selectNode() {
- this.view.dispatch(this.view.state.tr.setSelection(new TextSelection(this.view.state.doc.resolve(this.getPos()))));
+ this.view.dispatch(this.view.state.tr.setSelection(new TextSelection(this.view.state.doc.resolve(this.getPos() ?? 0))));
this.tbox._applyingChange = this.tbox.fieldKey; // setting focus will make prosemirror lose focus, which will cause it to change its selection to a text selection, which causes this view to get rebuilt but it's no longer node selected, so the equationview won't have focus
setTimeout(() => {
this._editor?.mathField.focus();
diff --git a/src/client/views/nodes/formattedText/FormattedTextBox.tsx b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
index c8b25e184..478039ffa 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -875,7 +875,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
})
);
const appearance = cm.findByDescription('Appearance...');
- const appearanceItems: ContextMenuProps[] = appearance && 'subitems' in appearance ? appearance.subitems : [];
+ const appearanceItems = appearance?.subitems ?? [];
appearanceItems.push({
description: !this.Document._layout_noSidebar ? 'Hide Sidebar Handle' : 'Show Sidebar Handle',
@@ -930,7 +930,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
!appearance && appearanceItems.length && cm.addItem({ description: 'Appearance...', subitems: appearanceItems, icon: 'eye' });
const options = cm.findByDescription('Options...');
- const optionItems = options && 'subitems' in options ? options.subitems : [];
+ const optionItems = options?.subitems ?? [];
optionItems.push({
description: `Toggle auto update from template`,
event: () => {
@@ -959,7 +959,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
});
!options && cm.addItem({ description: 'Options...', subitems: optionItems, icon: 'eye' });
const help = cm.findByDescription('Help...');
- const helpItems = help && 'subitems' in help ? help.subitems : [];
+ const helpItems = help?.subitems ?? [];
helpItems.push({ description: `show markdown options`, event: () => RTFMarkup.Instance.setOpen(true), icon: <BsMarkdownFill /> });
!help && cm.addItem({ description: 'Help...', subitems: helpItems, icon: 'eye' });
};