aboutsummaryrefslogtreecommitdiff
path: root/src/client/views
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views')
-rw-r--r--src/client/views/AntimodeMenu.tsx2
-rw-r--r--src/client/views/ContextMenu.tsx33
-rw-r--r--src/client/views/ContextMenuItem.tsx10
-rw-r--r--src/client/views/DashboardView.tsx6
-rw-r--r--src/client/views/FilterPanel.tsx12
-rw-r--r--src/client/views/GestureOverlay.tsx26
-rw-r--r--src/client/views/InkTranscription.tsx3
-rw-r--r--src/client/views/InkingStroke.tsx22
-rw-r--r--src/client/views/LightboxView.tsx22
-rw-r--r--src/client/views/Main.tsx18
-rw-r--r--src/client/views/MainView.tsx53
-rw-r--r--src/client/views/OverlayView.tsx21
-rw-r--r--src/client/views/ScriptingRepl.tsx54
-rw-r--r--src/client/views/StyleProvider.tsx6
-rw-r--r--src/client/views/ViewBoxInterface.ts3
-rw-r--r--src/client/views/collections/CollectionCalendarView.tsx4
-rw-r--r--src/client/views/collections/CollectionCardDeckView.tsx13
-rw-r--r--src/client/views/collections/CollectionCarouselView.tsx16
-rw-r--r--src/client/views/collections/CollectionDockingView.tsx68
-rw-r--r--src/client/views/collections/CollectionMasonryViewFieldRow.tsx20
-rw-r--r--src/client/views/collections/CollectionMenu.tsx4
-rw-r--r--src/client/views/collections/CollectionNoteTakingView.tsx29
-rw-r--r--src/client/views/collections/CollectionNoteTakingViewColumn.tsx15
-rw-r--r--src/client/views/collections/CollectionPileView.tsx10
-rw-r--r--src/client/views/collections/CollectionStackedTimeline.tsx21
-rw-r--r--src/client/views/collections/CollectionStackingView.tsx27
-rw-r--r--src/client/views/collections/CollectionSubView.tsx23
-rw-r--r--src/client/views/collections/CollectionTimeView.tsx8
-rw-r--r--src/client/views/collections/CollectionTreeView.tsx43
-rw-r--r--src/client/views/collections/TabDocView.tsx28
-rw-r--r--src/client/views/collections/TreeView.tsx86
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoState.tsx12
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormPannableContents.tsx4
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx65
-rw-r--r--src/client/views/collections/collectionLinear/CollectionLinearView.tsx10
-rw-r--r--src/client/views/nodes/AudioBox.tsx57
-rw-r--r--src/client/views/nodes/CollectionFreeFormDocumentView.tsx24
-rw-r--r--src/client/views/nodes/ComparisonBox.tsx7
-rw-r--r--src/client/views/nodes/DataVizBox/DataVizBox.tsx8
-rw-r--r--src/client/views/nodes/DataVizBox/SchemaCSVPopUp.tsx2
-rw-r--r--src/client/views/nodes/DataVizBox/components/TableBox.tsx56
-rw-r--r--src/client/views/nodes/DocumentContentsView.tsx46
-rw-r--r--src/client/views/nodes/DocumentLinksButton.tsx4
-rw-r--r--src/client/views/nodes/DocumentView.tsx39
-rw-r--r--src/client/views/nodes/EquationBox.tsx11
-rw-r--r--src/client/views/nodes/FieldView.tsx3
-rw-r--r--src/client/views/nodes/FontIconBox/ButtonInterface.ts12
-rw-r--r--src/client/views/nodes/FontIconBox/FontIconBox.tsx46
-rw-r--r--src/client/views/nodes/ImageBox.tsx9
-rw-r--r--src/client/views/nodes/KeyValueBox.tsx14
-rw-r--r--src/client/views/nodes/KeyValuePair.tsx9
-rw-r--r--src/client/views/nodes/LinkBox.tsx14
-rw-r--r--src/client/views/nodes/LinkDocPreview.tsx6
-rw-r--r--src/client/views/nodes/LoadingBox.tsx2
-rw-r--r--src/client/views/nodes/MapBox/MapBox.tsx8
-rw-r--r--src/client/views/nodes/PDFBox.tsx18
-rw-r--r--src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx15
-rw-r--r--src/client/views/nodes/RecordingBox/RecordingBox.tsx5
-rw-r--r--src/client/views/nodes/ScreenshotBox.tsx35
-rw-r--r--src/client/views/nodes/ScriptingBox.tsx96
-rw-r--r--src/client/views/nodes/VideoBox.tsx18
-rw-r--r--src/client/views/nodes/WebBox.tsx47
-rw-r--r--src/client/views/nodes/WebBoxRenderer.js18
-rw-r--r--src/client/views/nodes/audio/AudioWaveform.tsx2
-rw-r--r--src/client/views/nodes/formattedText/DashDocCommentView.tsx38
-rw-r--r--src/client/views/nodes/formattedText/DashDocView.tsx29
-rw-r--r--src/client/views/nodes/formattedText/DashFieldView.tsx34
-rw-r--r--src/client/views/nodes/formattedText/EquationEditor.tsx17
-rw-r--r--src/client/views/nodes/formattedText/EquationView.tsx22
-rw-r--r--src/client/views/nodes/formattedText/FormattedTextBox.tsx89
-rw-r--r--src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx4
-rw-r--r--src/client/views/nodes/formattedText/ParagraphNodeSpec.ts36
-rw-r--r--src/client/views/nodes/formattedText/RichTextMenu.tsx42
-rw-r--r--src/client/views/nodes/formattedText/RichTextRules.ts56
-rw-r--r--src/client/views/nodes/formattedText/marks_rts.ts40
-rw-r--r--src/client/views/nodes/formattedText/nodes_rts.ts91
-rw-r--r--src/client/views/pdf/GPTPopup/GPTPopup.tsx7
-rw-r--r--src/client/views/pdf/PDFViewer.tsx12
78 files changed, 974 insertions, 971 deletions
diff --git a/src/client/views/AntimodeMenu.tsx b/src/client/views/AntimodeMenu.tsx
index 303672d90..99dee6410 100644
--- a/src/client/views/AntimodeMenu.tsx
+++ b/src/client/views/AntimodeMenu.tsx
@@ -16,7 +16,7 @@ export abstract class AntimodeMenu<T extends AntimodeMenuProps> extends Observab
protected _mainCont: React.RefObject<HTMLDivElement> = React.createRef();
protected _dragging: boolean = false;
- constructor(props: any) {
+ constructor(props: T) {
super(props);
makeObservable(this);
}
diff --git a/src/client/views/ContextMenu.tsx b/src/client/views/ContextMenu.tsx
index d784a14b8..05634f376 100644
--- a/src/client/views/ContextMenu.tsx
+++ b/src/client/views/ContextMenu.tsx
@@ -2,7 +2,7 @@
/* eslint-disable react/jsx-props-no-spreading */
/* eslint-disable default-param-last */
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-import { action, computed, IReactionDisposer, makeObservable, observable } from 'mobx';
+import { action, computed, IReactionDisposer, makeObservable, observable, runInAction } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
import { DivHeight, DivWidth } from '../../ClientUtils';
@@ -12,7 +12,7 @@ import { ContextMenuItem, ContextMenuProps, OriginalMenuProps } from './ContextM
import { ObservableReactComponent } from './ObservableReactComponent';
@observer
-export class ContextMenu extends ObservableReactComponent<{}> {
+export class ContextMenu extends ObservableReactComponent<{ noexpand?: boolean }> {
// eslint-disable-next-line no-use-before-define
static Instance: ContextMenu;
@@ -39,7 +39,7 @@ export class ContextMenu extends ObservableReactComponent<{}> {
@observable _mouseY: number = -1;
@observable _shouldDisplay: boolean = false;
- constructor(props: any) {
+ constructor(props: object) {
super(props);
makeObservable(this);
ContextMenu.Instance = this;
@@ -151,21 +151,21 @@ export class ContextMenu extends ObservableReactComponent<{}> {
@computed get filteredItems(): (OriginalMenuProps | 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: any) => string[]) => {
+ const flattenItems = (items: ContextMenuProps[], groupFunc: (groupName: string) => string[]) => {
let eles: (OriginalMenuProps | string[])[] = [];
const leaves: OriginalMenuProps[] = [];
items.forEach(item => {
const { description } = item;
const path = groupFunc(description);
- if ('subitems' in item) {
+ if (item.subitems) {
const children = flattenItems(item.subitems, name => [...groupFunc(description), name]);
if (children.length || matches(path)) {
eles.push(path);
eles = eles.concat(children);
}
} else if (matches(path)) {
- leaves.push(item);
+ leaves.push(item as OriginalMenuProps);
}
});
@@ -182,7 +182,7 @@ export class ContextMenu extends ObservableReactComponent<{}> {
@computed get menuItems() {
if (!this._searchString) {
- return this._items.map((item, ind) => <ContextMenuItem key={item.description + ind} {...item} noexpand={this.itemsNeedSearch ? true : (item as any).noexpand} closeMenu={this.closeMenu} />);
+ return this._items.map((item, ind) => <ContextMenuItem key={item.description + ind} {...item} noexpand={this.itemsNeedSearch ? true : item.noexpand} closeMenu={this.closeMenu} />);
}
return this.filteredItems.map((value, index) =>
Array.isArray(value) ? (
@@ -201,7 +201,7 @@ export class ContextMenu extends ObservableReactComponent<{}> {
}
@computed get itemsNeedSearch() {
- return this._showSearch ? 1 : this._items.reduce((p, mi) => p + ((mi as any).noexpand ? 1 : (mi as any).subitems?.length || 1), 0) > 15;
+ return this._showSearch ? 1 : this._items.reduce((p, mi) => p + (mi.noexpand ? 1 : mi.subitems?.length || 1), 0) > 15;
}
_searchRef = React.createRef<HTMLInputElement>(); // bcz: we shouldn't need this, since we set autoFocus on the <input> tag, but for some reason we do...
@@ -211,13 +211,15 @@ export class ContextMenu extends ObservableReactComponent<{}> {
return (
<div
className="contextMenu-cont"
- ref={action((r: any) => {
- if (r) {
- this._width = DivWidth(r);
- this._height = DivHeight(r);
- }
- this._searchRef.current?.focus();
- })}
+ ref={r =>
+ runInAction(() => {
+ if (r) {
+ this._width = DivWidth(r);
+ this._height = DivHeight(r);
+ }
+ this._searchRef.current?.focus();
+ })
+ }
style={{
display: this._display ? '' : 'none',
left: this.pageX,
@@ -239,7 +241,6 @@ export class ContextMenu extends ObservableReactComponent<{}> {
value={this._searchString}
onKeyDown={this.onKeyDown}
onChange={this.onChange}
- // eslint-disable-next-line jsx-a11y/no-autofocus
autoFocus
/>
</span>
diff --git a/src/client/views/ContextMenuItem.tsx b/src/client/views/ContextMenuItem.tsx
index eb1030eec..3b87ea58b 100644
--- a/src/client/views/ContextMenuItem.tsx
+++ b/src/client/views/ContextMenuItem.tsx
@@ -10,8 +10,10 @@ import { ObservableReactComponent } from './ObservableReactComponent';
export interface OriginalMenuProps {
description: string;
- event: (stuff?: any) => void;
+ event: (stuff?: unknown) => void;
undoable?: boolean;
+ noexpand?: boolean;
+ subitems?: ContextMenuProps[];
icon: IconProp | JSX.Element; // maybe should be optional (icon?)
closeMenu?: () => void;
}
@@ -33,7 +35,7 @@ export class ContextMenuItem extends ObservableReactComponent<ContextMenuProps &
@observable private _items: Array<ContextMenuProps> = [];
@observable private overItem = false;
- constructor(props: any) {
+ constructor(props: ContextMenuProps & { selected?: boolean }) {
super(props);
makeObservable(this);
}
@@ -56,7 +58,7 @@ export class ContextMenuItem extends ObservableReactComponent<ContextMenuProps &
}
};
- currentTimeout?: any;
+ currentTimeout?: NodeJS.Timeout | undefined;
static readonly timeout = 300;
_overPosY = 0;
_overPosX = 0;
@@ -94,7 +96,7 @@ export class ContextMenuItem extends ObservableReactComponent<ContextMenuProps &
);
};
- isJSXElement(val: any): val is JSX.Element {
+ isJSXElement(val: unknown): val is JSX.Element {
return React.isValidElement(val);
}
diff --git a/src/client/views/DashboardView.tsx b/src/client/views/DashboardView.tsx
index b7383a37e..dcc5442f0 100644
--- a/src/client/views/DashboardView.tsx
+++ b/src/client/views/DashboardView.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 { Button, ColorPicker, EditableText, Size, Type } from 'browndash-components';
import { action, computed, makeObservable, observable } from 'mobx';
@@ -46,7 +44,7 @@ export type DocConfig = {
// DashboardView is the view with the dashboard previews, rendered when the app first loads
@observer
-export class DashboardView extends ObservableReactComponent<{}> {
+export class DashboardView extends ObservableReactComponent<object> {
public static _urlState: HistoryUtil.DocUrl;
public static makeDocumentConfig(document: Doc, panelName?: string, width?: number, keyValue?: boolean) {
return {
@@ -82,7 +80,7 @@ export class DashboardView extends ObservableReactComponent<{}> {
});
return doc;
}
- constructor(props: any) {
+ constructor(props: object) {
super(props);
makeObservable(this);
}
diff --git a/src/client/views/FilterPanel.tsx b/src/client/views/FilterPanel.tsx
index c97edd7f0..b11fa3bd5 100644
--- a/src/client/views/FilterPanel.tsx
+++ b/src/client/views/FilterPanel.tsx
@@ -1,6 +1,4 @@
/* eslint-disable react/jsx-props-no-spreading */
-/* eslint-disable jsx-a11y/no-static-element-interactions */
-/* eslint-disable jsx-a11y/click-events-have-key-events */
import { action, computed, makeObservable, observable, ObservableMap } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
@@ -28,7 +26,7 @@ interface filterProps {
export class FilterPanel extends ObservableReactComponent<filterProps> {
@observable _selectedFacetHeaders = new Set<string>();
- constructor(props: any) {
+ constructor(props: filterProps) {
super(props);
makeObservable(this);
}
@@ -41,7 +39,7 @@ export class FilterPanel extends ObservableReactComponent<filterProps> {
}
@computed get targetDocChildKey() {
const targetView = DocumentView.getFirstDocumentView(this.Document);
- return targetView?.ComponentView?.annotationKey ?? targetView?.ComponentView?.fieldKey ?? 'data';
+ return targetView?.ComponentView?.annotationKey || (targetView?.ComponentView?.fieldKey ?? 'data');
}
@computed get targetDocChildren() {
return [...DocListCast(this.Document?.[this.targetDocChildKey] || Doc.ActiveDashboard?.data), ...DocListCast(this.Document[Doc.LayoutFieldKey(this.Document) + '_sidebar'])];
@@ -240,7 +238,7 @@ export class FilterPanel extends ObservableReactComponent<filterProps> {
{Array.from(this.activeRenderedFacetInfos.keys()).map(
// iterate over activeFacetRenderInfos ==> renderInfo which you can renderInfo.facetHeader
renderInfo => (
- <div>
+ <div key={renderInfo.facetHeader}>
<div className="filterBox-facetHeader">
<div className="filterBox-facetHeader-Header"> </div>
{renderInfo.facetHeader.charAt(0).toUpperCase() + renderInfo.facetHeader.slice(1)}
@@ -308,7 +306,7 @@ export class FilterPanel extends ObservableReactComponent<filterProps> {
return this.facetValues(facetHeader).map(fval => {
const facetValue = fval;
return (
- <div>
+ <div key={facetValue}>
<input
style={{ width: 20, marginLeft: 20 }}
checked={['check', 'exists'].includes(
@@ -343,7 +341,7 @@ export class FilterPanel extends ObservableReactComponent<filterProps> {
<div className="slider-handles">
{handles.map(handle => (
// const value = i === 0 ? defaultValues[0] : defaultValues[1];
- <div>
+ <div key={handle.id}>
<Handle key={handle.id} handle={handle} domain={domain} isActive={handle.id === activeHandleID} getHandleProps={getHandleProps} />
</div>
))}
diff --git a/src/client/views/GestureOverlay.tsx b/src/client/views/GestureOverlay.tsx
index e3e252593..804c41091 100644
--- a/src/client/views/GestureOverlay.tsx
+++ b/src/client/views/GestureOverlay.tsx
@@ -78,7 +78,7 @@ export class GestureOverlay extends ObservableReactComponent<React.PropsWithChil
private thumbIdentifier?: number;
private pointerIdentifier?: number;
- constructor(props: any) {
+ constructor(props: GestureOverlayProps) {
super(props);
makeObservable(this);
GestureOverlay.Instances.push(this);
@@ -94,7 +94,7 @@ export class GestureOverlay extends ObservableReactComponent<React.PropsWithChil
@action
onPointerDown = (e: React.PointerEvent) => {
- if (!(e.target as any)?.className?.toString().startsWith('lm_')) {
+ if (!(e.target as HTMLElement)?.className?.toString().startsWith('lm_')) {
if ([InkTool.Highlighter, InkTool.Pen, InkTool.Write].includes(Doc.ActiveTool)) {
this._points.push({ X: e.clientX, Y: e.clientY });
setupMoveUpEvents(this, e, this.onPointerMove, this.onPointerUp, emptyFunction);
@@ -173,8 +173,8 @@ export class GestureOverlay extends ObservableReactComponent<React.PropsWithChil
newPoints.pop();
const controlPoints: { X: number; Y: number }[] = [];
- const bezierCurves = (fitCurve as any)(newPoints, 10);
- Array.from(bezierCurves).forEach((curve: any) => {
+ const bezierCurves = fitCurve.default(newPoints, 10);
+ Array.from(bezierCurves).forEach(curve => {
controlPoints.push({ X: curve[0][0], Y: curve[0][1] });
controlPoints.push({ X: curve[1][0], Y: curve[1][1] });
controlPoints.push({ X: curve[2][0], Y: curve[2][1] });
@@ -351,7 +351,7 @@ export class GestureOverlay extends ObservableReactComponent<React.PropsWithChil
return false;
};
- dispatchGesture = (gesture: Gestures, stroke?: InkData, text?: any) => {
+ dispatchGesture = (gesture: Gestures, stroke?: InkData, text?: string) => {
const points = (stroke ?? this._points).slice();
return (
document.elementFromPoint(points[0].X, points[0].Y)?.dispatchEvent(
@@ -411,7 +411,7 @@ export class GestureOverlay extends ObservableReactComponent<React.PropsWithChil
ActiveDash(),
1,
1,
- this.InkShape ?? '',
+ this.InkShape as Gestures,
'none',
1.0,
false
@@ -438,7 +438,7 @@ export class GestureOverlay extends ObservableReactComponent<React.PropsWithChil
ActiveDash(),
1,
1,
- this.InkShape ?? '',
+ this.InkShape as Gestures,
'none',
1.0,
false
@@ -516,13 +516,7 @@ export class GestureOverlay extends ObservableReactComponent<React.PropsWithChil
ScriptingGlobals.add('GestureOverlay', GestureOverlay);
// eslint-disable-next-line prefer-arrow-callback
-ScriptingGlobals.add(function setToolglass(tool: any) {
- runInAction(() => {
- GestureOverlay.Instance.Tool = tool;
- });
-});
-// eslint-disable-next-line prefer-arrow-callback
-ScriptingGlobals.add(function setPen(width: any, color: any, fill: any, arrowStart: any, arrowEnd: any, dash: any) {
+ScriptingGlobals.add(function setPen(width: string, color: string, fill: string, arrowStart: string, arrowEnd: string, dash: string) {
runInAction(() => {
GestureOverlay.Instance.SavedColor = ActiveInkColor();
SetActiveInkColor(color);
@@ -543,8 +537,8 @@ ScriptingGlobals.add(function resetPen() {
}, 'resets the pen tool');
ScriptingGlobals.add(
// eslint-disable-next-line prefer-arrow-callback
- function createText(text: any, x: any, y: any) {
- GestureOverlay.Instance.dispatchGesture(Gestures.Text, [{ X: x, Y: y }], text);
+ function createText(text: string, X: number, Y: number) {
+ GestureOverlay.Instance.dispatchGesture(Gestures.Text, [{ X, Y }], text);
},
'creates a text document with inputted text and coordinates',
'(text: any, x: any, y: any)'
diff --git a/src/client/views/InkTranscription.tsx b/src/client/views/InkTranscription.tsx
index 1ed8de1be..33db72960 100644
--- a/src/client/views/InkTranscription.tsx
+++ b/src/client/views/InkTranscription.tsx
@@ -240,7 +240,8 @@
// const text = exports['text/plain'];
// if (this.currGroup) {
-// this.currGroup.transcription = text;
+// this.currGroup.text = text; // transcription text
+// this.currGroup.icon_fieldKey = 'transcription'; // use the transcription icon template when iconifying
// this.currGroup.title = text.split('\n')[0];
// }
diff --git a/src/client/views/InkingStroke.tsx b/src/client/views/InkingStroke.tsx
index 784d252a3..2e82371cb 100644
--- a/src/client/views/InkingStroke.tsx
+++ b/src/client/views/InkingStroke.tsx
@@ -20,6 +20,7 @@
Most of the operations that can be performed on an InkStroke (eg delete a point, rotate, stretch) are implemented in the InkStrokeProperties helper class
*/
+import { Property } from 'csstype';
import { action, computed, IReactionDisposer, observable, reaction } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
@@ -28,6 +29,7 @@ import { Doc } from '../../fields/Doc';
import { InkData, InkField } from '../../fields/InkField';
import { BoolCast, Cast, NumCast, RTFCast, StrCast } from '../../fields/Types';
import { TraceMobx } from '../../fields/util';
+import { Gestures } from '../../pen-gestures/GestureTypes';
import { CognitiveServices } from '../cognitive_services/CognitiveServices';
import { Docs } from '../documents/Documents';
import { DocumentType } from '../documents/DocumentTypes';
@@ -35,7 +37,6 @@ import { InteractionUtils } from '../util/InteractionUtils';
import { SnappingManager } from '../util/SnappingManager';
import { UndoManager } from '../util/UndoManager';
import { ContextMenu } from './ContextMenu';
-import { ViewBoxInterface } from './ViewBoxInterface';
import { ViewBoxAnnotatableComponent } from './DocComponent';
import { Colors } from './global/globalEnums';
import { InkControlPtHandles, InkEndPtHandles } from './InkControlPtHandles';
@@ -46,6 +47,7 @@ import { FieldView, FieldViewProps } from './nodes/FieldView';
import { FormattedTextBox, FormattedTextBoxProps } from './nodes/formattedText/FormattedTextBox';
import { PinDocView, PinProps } from './PinFuncs';
import { StyleProp } from './StyleProp';
+import { ViewBoxInterface } from './ViewBoxInterface';
// eslint-disable-next-line @typescript-eslint/no-var-requires
const { INK_MASK_SIZE } = require('./global/globalCssVariables.module.scss'); // prettier-ignore
@@ -318,8 +320,8 @@ export class InkingStroke extends ViewBoxAnnotatableComponent<FieldViewProps>()
Colors.MEDIUM_BLUE,
screenInkWidth[0],
screenSpaceCenterlineStrokeWidth,
- StrCast(inkDoc.stroke_lineJoin),
- StrCast(this.layoutDoc.stroke_lineCap),
+ StrCast(inkDoc.stroke_lineJoin) as Property.StrokeLinejoin,
+ StrCast(this.layoutDoc.stroke_lineCap) as Property.StrokeLinecap,
StrCast(inkDoc.stroke_bezier),
'none',
startMarker,
@@ -328,7 +330,7 @@ export class InkingStroke extends ViewBoxAnnotatableComponent<FieldViewProps>()
StrCast(inkDoc.stroke_dash),
1,
1,
- '',
+ '' as Gestures,
'none',
1.0,
false
@@ -383,8 +385,8 @@ export class InkingStroke extends ViewBoxAnnotatableComponent<FieldViewProps>()
this.strokeColor,
inkStrokeWidth,
inkStrokeWidth,
- StrCast(this.layoutDoc.stroke_lineJoin),
- StrCast(this.layoutDoc.stroke_lineCap),
+ StrCast(this.layoutDoc.stroke_lineJoin) as Property.StrokeLinejoin,
+ StrCast(this.layoutDoc.stroke_lineCap) as Property.StrokeLinecap,
StrCast(this.layoutDoc.stroke_bezier),
!closed ? 'none' : fillColor === 'transparent' ? 'none' : fillColor,
startMarker,
@@ -393,7 +395,7 @@ export class InkingStroke extends ViewBoxAnnotatableComponent<FieldViewProps>()
StrCast(this.layoutDoc.stroke_dash),
inkScaleX,
inkScaleY,
- '',
+ '' as Gestures,
'none',
1.0,
false,
@@ -410,8 +412,8 @@ export class InkingStroke extends ViewBoxAnnotatableComponent<FieldViewProps>()
mask && color === 'transparent' ? this.strokeColor : (highlightColor ?? color),
inkStrokeWidth,
inkStrokeWidth + NumCast(this.layoutDoc.stroke_borderWidth) + (fillColor ? (closed ? higlightMargin : (highlightIndex ?? 0) + higlightMargin) : higlightMargin),
- StrCast(this.layoutDoc.stroke_lineJoin),
- StrCast(this.layoutDoc.stroke_lineCap),
+ StrCast(this.layoutDoc.stroke_lineJoin) as Property.StrokeLinejoin,
+ StrCast(this.layoutDoc.stroke_lineCap) as Property.StrokeLinecap,
StrCast(this.layoutDoc.stroke_bezier),
!closed || !fillColor || DashColor(fillColor).alpha() === 0 ? 'none' : fillColor,
startMarker,
@@ -420,7 +422,7 @@ export class InkingStroke extends ViewBoxAnnotatableComponent<FieldViewProps>()
StrCast(this.layoutDoc.stroke_dash),
inkScaleX,
inkScaleY,
- '',
+ '' as Gestures,
this._props.pointerEvents?.() ?? 'visiblePainted',
0.0,
false,
diff --git a/src/client/views/LightboxView.tsx b/src/client/views/LightboxView.tsx
index 7198c7f05..adbe20a63 100644
--- a/src/client/views/LightboxView.tsx
+++ b/src/client/views/LightboxView.tsx
@@ -1,6 +1,4 @@
/* eslint-disable no-use-before-define */
-/* eslint-disable jsx-a11y/no-static-element-interactions */
-/* eslint-disable jsx-a11y/click-events-have-key-events */
import { IconProp } from '@fortawesome/fontawesome-svg-core';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { Toggle, ToggleType, Type } from 'browndash-components';
@@ -12,7 +10,7 @@ import { emptyFunction } from '../../Utils';
import { CreateLinkToActiveAudio, Doc, DocListCast, FieldResult, Opt } from '../../fields/Doc';
import { Id } from '../../fields/FieldSymbols';
import { InkTool } from '../../fields/InkField';
-import { Cast, NumCast, toList } from '../../fields/Types';
+import { BoolCast, Cast, NumCast, toList } from '../../fields/Types';
import { SnappingManager } from '../util/SnappingManager';
import { Transform } from '../util/Transform';
import { GestureOverlay } from './GestureOverlay';
@@ -28,7 +26,7 @@ interface LightboxViewProps {
PanelWidth: number;
PanelHeight: number;
maxBorder: number[];
- addSplit: (document: Doc, pullSide: OpenWhereMod, stack?: any, panelName?: string | undefined, keyValue?: boolean | undefined) => boolean;
+ addSplit: (document: Doc, pullSide: OpenWhereMod, stack?: unknown, panelName?: string | undefined, keyValue?: boolean | undefined) => boolean;
}
const savedKeys = ['freeform_panX', 'freeform_panY', 'freeform_scale', 'layout_scrollTop', 'layout_fieldKey'];
@@ -63,7 +61,7 @@ export class LightboxView extends ObservableReactComponent<LightboxViewProps> {
@computed get leftBorder() { return Math.min(this._props.PanelWidth / 4, this._props.maxBorder[0]); } // prettier-ignore
@computed get topBorder() { return Math.min(this._props.PanelHeight / 4, this._props.maxBorder[1]); } // prettier-ignore
- constructor(props: any) {
+ constructor(props: LightboxViewProps) {
super(props);
makeObservable(this);
LightboxView.Instance = this;
@@ -214,7 +212,7 @@ export class LightboxView extends ObservableReactComponent<LightboxViewProps> {
lightboxDocTemplate = () => this._layoutTemplate;
future = () => this._future;
- renderNavBtn = (left: Opt<string | number>, bottom: Opt<number>, top: number, icon: IconProp, display: any, click: () => void, color?: string) => (
+ renderNavBtn = (left: Opt<string | number>, bottom: Opt<number>, top: number, icon: IconProp, display: boolean, click: () => void, color?: string) => (
<div
className="lightboxView-navBtn-frame"
style={{
@@ -239,7 +237,7 @@ export class LightboxView extends ObservableReactComponent<LightboxViewProps> {
render() {
let downx = 0;
let downy = 0;
- const toggleBtn = (classname: string, tooltip: string, toggleBackground: any, icon: IconProp, icon2: IconProp | string, onClick: () => void) => (
+ const toggleBtn = (classname: string, tooltip: string, toggleBackground: boolean, icon: IconProp, icon2: IconProp | string, onClick: () => void) => (
<div className={classname}>
<Toggle
tooltip={tooltip}
@@ -306,18 +304,18 @@ export class LightboxView extends ObservableReactComponent<LightboxViewProps> {
</GestureOverlay>
</div>
- {this.renderNavBtn(0, undefined, this._props.PanelHeight / 2 - 12.5, 'chevron-left', this._doc && this._history.length, this.previous)}
+ {this.renderNavBtn(0, undefined, this._props.PanelHeight / 2 - 12.5, 'chevron-left', this._doc && this._history.length ? true : false, this.previous)}
{this.renderNavBtn(
this._props.PanelWidth - Math.min(this._props.PanelWidth / 4, this._props.maxBorder[0]),
undefined,
this._props.PanelHeight / 2 - 12.5,
'chevron-right',
- this._doc && this._future.length,
+ this._doc && this._future.length ? true : false,
this.next,
this.future().length.toString()
)}
<LightboxTourBtn lightboxDoc={this.lightboxDoc} navBtn={this.renderNavBtn} future={this.future} stepInto={this.stepInto} />
- {toggleBtn('lightboxView-navBtn', 'toggle reading view', this._doc?._layout_fitWidth, 'book-open', 'book', this.toggleFitWidth)}
+ {toggleBtn('lightboxView-navBtn', 'toggle reading view', BoolCast(this._doc?._layout_fitWidth), 'book-open', 'book', this.toggleFitWidth)}
{toggleBtn('lightboxView-tabBtn', 'open document in a tab', false, 'file-download', '', this.downloadDoc)}
{toggleBtn('lightboxView-penBtn', 'toggle pen annotation', Doc.ActiveTool === InkTool.Pen, 'pen', '', this.togglePen)}
{toggleBtn('lightboxView-exploreBtn', 'toggle navigate only mode', SnappingManager.ExploreMode, 'globe-americas', '', this.toggleExplore)}
@@ -326,7 +324,7 @@ export class LightboxView extends ObservableReactComponent<LightboxViewProps> {
}
}
interface LightboxTourBtnProps {
- navBtn: (left: Opt<string | number>, bottom: Opt<number>, top: number, icon: IconProp, display: any, click: () => void, color?: string) => JSX.Element;
+ navBtn: (left: Opt<string | number>, bottom: Opt<number>, top: number, icon: IconProp, display: boolean, click: () => void, color?: string) => JSX.Element;
// eslint-disable-next-line react/no-unused-prop-types
future: () => Opt<Doc[]>;
stepInto: () => void;
@@ -335,7 +333,7 @@ interface LightboxTourBtnProps {
@observer
export class LightboxTourBtn extends React.Component<LightboxTourBtnProps> {
render() {
- return this.props.navBtn('50%', 0, 0, 'chevron-down', this.props.lightboxDoc(), this.props.stepInto, '');
+ return this.props.navBtn('50%', 0, 0, 'chevron-down', this.props.lightboxDoc() ? true : false, this.props.stepInto, '');
}
}
diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx
index 43b9a6b39..044162e4e 100644
--- a/src/client/views/Main.tsx
+++ b/src/client/views/Main.tsx
@@ -50,6 +50,7 @@ import { ScreenshotBox } from './nodes/ScreenshotBox';
import { ScriptingBox } from './nodes/ScriptingBox';
import { VideoBox } from './nodes/VideoBox';
import { WebBox } from './nodes/WebBox';
+import { CalendarBox } from './nodes/calendarBox/CalendarBox';
import { DashDocCommentView } from './nodes/formattedText/DashDocCommentView';
import { DashDocView } from './nodes/formattedText/DashDocView';
import { DashFieldView } from './nodes/formattedText/DashFieldView';
@@ -60,6 +61,8 @@ import { SummaryView } from './nodes/formattedText/SummaryView';
import { ImportElementBox } from './nodes/importBox/ImportElementBox';
import { PresBox, PresElementBox } from './nodes/trails';
import { SearchBox } from './search/SearchBox';
+import { Node } from 'prosemirror-model';
+import { EditorView } from 'prosemirror-view';
dotenv.config();
@@ -83,7 +86,7 @@ FieldLoader.ServerLoadStatus = { requested: 0, retrieved: 0, message: 'cache' };
setTimeout(() => {
// prevent zooming browser
document.getElementById('root')!.addEventListener('wheel', event => event.ctrlKey && event.preventDefault(), true);
- const startload = (document as any).startLoad;
+ const startload = (document as unknown as { startLoad: number }).startLoad; // see index.html in deploy/
const loading = Date.now() - (startload ? Number(startload) : Date.now() - 3000);
console.log('Loading Time = ' + loading);
const d = new Date();
@@ -99,12 +102,12 @@ FieldLoader.ServerLoadStatus = { requested: 0, retrieved: 0, message: 'cache' };
// initialize plugins and classes that require plugins
CollectionDockingView.Init(TabDocView);
FormattedTextBox.Init((tbox: FormattedTextBox) => ({
- dashComment(node: any, view: any, getPos: any) { return new DashDocCommentView(node, view, getPos); }, // prettier-ignore
- dashDoc(node: any, view: any, getPos: any) { return new DashDocView(node, view, getPos, tbox); }, // prettier-ignore
- dashField(node: any, view: any, getPos: any) { return new DashFieldView(node, view, getPos, tbox); }, // prettier-ignore
- equation(node: any, view: any, getPos: any) { return new EquationView(node, view, getPos, tbox); }, // prettier-ignore
- summary(node: any, view: any, getPos: any) { return new SummaryView(node, view, getPos); }, // prettier-ignore
- footnote(node: any, view: any, getPos: any) { return new FootnoteView(node, view, getPos); }, // prettier-ignore
+ dashComment(node: Node, view: EditorView, getPos: () => number | undefined) { return new DashDocCommentView(node, view, getPos); }, // prettier-ignore
+ dashDoc(node: Node, view: EditorView, getPos: () => number | undefined) { return new DashDocView(node, view, getPos, tbox); }, // prettier-ignore
+ dashField(node: Node, view: EditorView, getPos: () => number | undefined) { return new DashFieldView(node, view, getPos, tbox); }, // prettier-ignore
+ equation(node: Node, view: EditorView, getPos: () => number | undefined) { return new EquationView(node, view, getPos, tbox); }, // prettier-ignore
+ summary(node: Node, view: EditorView, getPos: () => number | undefined) { return new SummaryView(node, view, getPos); }, // prettier-ignore
+ footnote(node: Node, view: EditorView, getPos: () => number | undefined) { return new FootnoteView(node, view, getPos); }, // prettier-ignore
}));
CollectionFreeFormInfoUI.Init();
LinkFollower.Init();
@@ -141,6 +144,7 @@ FieldLoader.ServerLoadStatus = { requested: 0, retrieved: 0, message: 'cache' };
ChatBox,
DiagramBox,
HTMLtag,
+ CalendarBox,
ComparisonBox,
LoadingBox,
PhysicsSimulationBox,
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index ef1bcfb64..ac30c5a14 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -1,4 +1,3 @@
-/* eslint-disable node/no-unpublished-import */
import { library } from '@fortawesome/fontawesome-svg-core';
import { faBuffer, faHireAHelper } from '@fortawesome/free-brands-svg-icons';
import * as far from '@fortawesome/free-regular-svg-icons';
@@ -7,7 +6,7 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { action, computed, configure, makeObservable, observable, reaction, runInAction } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
-// eslint-disable-next-line import/no-relative-packages
+import ResizeObserver from 'resize-observer-polyfill';
import '../../../node_modules/browndash-components/dist/styles/global.min.css';
import { ClientUtils, lightOrDark, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnTrue, returnZero, setupMoveUpEvents } from '../../ClientUtils';
import { emptyFunction } from '../../Utils';
@@ -58,7 +57,6 @@ import { ImageLabelHandler } from './collections/collectionFreeForm/ImageLabelHa
import { MarqueeOptionsMenu } from './collections/collectionFreeForm/MarqueeOptionsMenu';
import { CollectionLinearView } from './collections/collectionLinear';
import { LinkMenu } from './linking/LinkMenu';
-import { AudioBox } from './nodes/AudioBox';
import { SchemaCSVPopUp } from './nodes/DataVizBox/SchemaCSVPopUp';
import { DocButtonState } from './nodes/DocumentLinksButton';
import { DocumentView, DocumentViewInternal } from './nodes/DocumentView';
@@ -77,11 +75,11 @@ import { AnchorMenu } from './pdf/AnchorMenu';
import { GPTPopup } from './pdf/GPTPopup/GPTPopup';
import { TopBar } from './topbar/TopBar';
+// eslint-disable-next-line @typescript-eslint/no-var-requires
const { LEFT_MENU_WIDTH, TOPBAR_HEIGHT } = require('./global/globalCssVariables.module.scss'); // prettier-ignore
-const _global = (window /* browser */ || global) /* node */ as any;
@observer
-export class MainView extends ObservableReactComponent<{}> {
+export class MainView extends ObservableReactComponent<object> {
// eslint-disable-next-line no-use-before-define
public static Instance: MainView;
public static Live: boolean = false;
@@ -92,7 +90,7 @@ export class MainView extends ObservableReactComponent<{}> {
@observable private _dashUIWidth: number = 0; // width of entire main dashboard region including left menu buttons and properties panel (but not including the dashboard selector button row)
@observable private _dashUIHeight: number = 0; // height of entire main dashboard region including top menu buttons
@observable private _panelContent: string = 'none';
- @observable private _sidebarContent: any = Doc.MyLeftSidebarPanel;
+ @observable private _sidebarContent: Doc = Doc.MyLeftSidebarPanel;
@observable private _leftMenuFlyoutWidth: number = 0;
@computed get _hideUI() {
return this.mainDoc && this.mainDoc._type_collection !== CollectionViewType.Docking;
@@ -152,7 +150,7 @@ export class MainView extends ObservableReactComponent<{}> {
}
};
headerBarDocWidth = () => this.mainDocViewWidth();
- headerBarDocHeight = () => (this._hideUI ? 0 : this.headerBarHeight ?? 0);
+ headerBarDocHeight = () => (this._hideUI ? 0 : (this.headerBarHeight ?? 0));
topMenuHeight = () => (this._hideUI ? 0 : 35);
topMenuWidth = returnZero; // value is ignored ...
leftMenuWidth = () => (this._hideUI ? 0 : Number(LEFT_MENU_WIDTH.replace('px', '')));
@@ -169,7 +167,7 @@ export class MainView extends ObservableReactComponent<{}> {
reaction(
// when a multi-selection occurs, remove focus from all active elements to allow keyboad input to go only to global key manager to act upon selection
() => DocumentView.Selected().slice(),
- views => views.length > 1 && (document.activeElement as any)?.blur !== undefined && (document.activeElement as any)!.blur()
+ views => views.length > 1 && document.activeElement instanceof HTMLElement && document.activeElement?.blur()
);
reaction(
() => Doc.MyDockedBtns.linearView_IsOpen,
@@ -234,9 +232,9 @@ export class MainView extends ObservableReactComponent<{}> {
tag.src = 'https://www.youtube.com/iframe_api';
const firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode!.insertBefore(tag, firstScriptTag);
- document.addEventListener('dash', (e: any) => {
+ document.addEventListener('dash', (e: Event) => {
// event used by chrome plugin to tell Dash which document to focus on
- const id = GetDocFromUrl(e.detail);
+ const id = GetDocFromUrl((e as Event & { detail: string }).detail);
DocServer.GetRefField(id).then(doc => (doc instanceof Doc ? DocumentView.showDocument(doc, { willPan: false }) : null));
});
document.addEventListener('linkAnnotationToDash', Hypothesis.linkListener);
@@ -253,12 +251,12 @@ export class MainView extends ObservableReactComponent<{}> {
// document.removeEventListener('linkAnnotationToDash', Hypothesis.linkListener);
}
- constructor(props: any) {
+ constructor(props: object) {
super(props);
makeObservable(this);
DocumentViewInternal.addDocTabFunc = MainView.addDocTabFunc_impl;
MainView.Instance = this;
- DashboardView._urlState = HistoryUtil.parseUrl(window.location) || ({} as any);
+ DashboardView._urlState = HistoryUtil.parseUrl(window.location) ?? { type: 'doc', docId: '' };
// causes errors to be generated when modifying an observable outside of an action
configure({ enforceActions: 'observed' });
@@ -293,7 +291,7 @@ export class MainView extends ObservableReactComponent<{}> {
fa.faExternalLinkAlt,
fa.faCalendar,
fa.faSquare,
- far.faSquare as any,
+ far.faSquare,
fa.faConciergeBell,
fa.faWindowRestore,
fa.faFolder,
@@ -445,7 +443,7 @@ export class MainView extends ObservableReactComponent<{}> {
fa.faHandPaper,
fa.faMap,
fa.faUser,
- faHireAHelper as any,
+ faHireAHelper,
fa.faTrashRestore,
fa.faUsers,
fa.faWrench,
@@ -456,14 +454,14 @@ export class MainView extends ObservableReactComponent<{}> {
fa.faArchive,
fa.faBezierCurve,
fa.faCircle,
- far.faCircle as any,
+ far.faCircle,
fa.faLongArrowAltRight,
fa.faPenFancy,
fa.faAngleDoubleRight,
fa.faAngleDoubleDown,
fa.faAngleDoubleLeft,
fa.faAngleDoubleUp,
- faBuffer as any,
+ faBuffer,
fa.faExpand,
fa.faUndo,
fa.faSlidersH,
@@ -570,7 +568,6 @@ export class MainView extends ObservableReactComponent<{}> {
);
DocumentManager.removeOverlayViews();
Doc.linkFollowUnhighlight();
- AudioBox.Enabled = true;
const targets = document.elementsFromPoint(e.x, e.y);
if (targets.length) {
let targClass = targets[0].className.toString();
@@ -590,18 +587,6 @@ export class MainView extends ObservableReactComponent<{}> {
document.addEventListener('pointerdown', this.globalPointerDown, true);
document.addEventListener('pointermove', this.globalPointerMove, true);
document.addEventListener('pointerup', this.globalPointerClick, true);
- document.addEventListener(
- 'click',
- (e: MouseEvent) => {
- if (!e.cancelBubble) {
- const pathstr = (e as any)?.path?.map((p: any) => p.classList?.toString()).join();
- if (pathstr?.includes('libraryFlyout')) {
- DocumentView.DeselectAll();
- }
- }
- },
- false
- );
document.oncontextmenu = () => false;
};
@@ -777,7 +762,7 @@ export class MainView extends ObservableReactComponent<{}> {
<div key="libFlyout" className="mainView-libraryFlyout" style={{ minWidth: this._leftMenuFlyoutWidth, width: this._leftMenuFlyoutWidth }}>
<div className="mainView-contentArea">
<DocumentView
- Document={this._sidebarContent.proto || this._sidebarContent}
+ Document={DocCast(this._sidebarContent.proto, this._sidebarContent)}
addDocument={undefined}
addDocTab={DocumentViewInternal.addDocTabFunc}
pinToPres={DocumentView.PinDoc}
@@ -889,7 +874,7 @@ export class MainView extends ObservableReactComponent<{}> {
className="mainView-dashboardArea"
ref={r => {
r &&
- new _global.ResizeObserver(
+ new ResizeObserver(
action(() => {
this._dashUIWidth = r.getBoundingClientRect().width;
this._dashUIHeight = r.getBoundingClientRect().height;
@@ -976,11 +961,11 @@ export class MainView extends ObservableReactComponent<{}> {
{[
...SnappingManager.HorizSnapLines.map((l, i) => (
// eslint-disable-next-line react/no-array-index-key
- <line key={'horiz' + i} x1="0" y1={l} x2="2000" y2={l} stroke={lightOrDark(dragPar.layoutDoc.backgroundColor ?? 'gray')} opacity={0.3} strokeWidth={1} strokeDasharray="2 2" />
+ <line key={'horiz' + i} x1="0" y1={l} x2="2000" y2={l} stroke={lightOrDark(StrCast(dragPar.layoutDoc.backgroundColor, 'gray'))} opacity={0.3} strokeWidth={1} strokeDasharray="2 2" />
)),
...SnappingManager.VertSnapLines.map((l, i) => (
// eslint-disable-next-line react/no-array-index-key
- <line key={'vert' + i} y1={this.topOfMainDocContent.toString()} x1={l} y2="2000" x2={l} stroke={lightOrDark(dragPar.layoutDoc.backgroundColor ?? 'gray')} opacity={0.3} strokeWidth={1} strokeDasharray="2 2" />
+ <line key={'vert' + i} y1={this.topOfMainDocContent.toString()} x1={l} y2="2000" x2={l} stroke={lightOrDark(StrCast(dragPar.layoutDoc.backgroundColor, 'gray'))} opacity={0.3} strokeWidth={1} strokeDasharray="2 2" />
)),
]}
</svg>
@@ -1038,7 +1023,7 @@ export class MainView extends ObservableReactComponent<{}> {
}
ref={r => {
r &&
- new _global.ResizeObserver(
+ new ResizeObserver(
action(() => {
this._windowWidth = r.getBoundingClientRect().width;
this._windowHeight = r.getBoundingClientRect().height;
diff --git a/src/client/views/OverlayView.tsx b/src/client/views/OverlayView.tsx
index a7907a565..7bf10467e 100644
--- a/src/client/views/OverlayView.tsx
+++ b/src/client/views/OverlayView.tsx
@@ -3,6 +3,7 @@ import { observer } from 'mobx-react';
import { computedFn } from 'mobx-utils';
import * as React from 'react';
import ReactLoading from 'react-loading';
+import ResizeObserver from 'resize-observer-polyfill';
import { returnEmptyDoclist, returnEmptyFilter, returnTrue, setupMoveUpEvents } from '../../ClientUtils';
import { Utils, emptyFunction } from '../../Utils';
import { Doc } from '../../fields/Doc';
@@ -18,8 +19,6 @@ import './OverlayView.scss';
import { DefaultStyleProvider } from './StyleProvider';
import { DocumentView, DocumentViewInternal } from './nodes/DocumentView';
-const _global = (window /* browser */ || global) /* node */ as any;
-
export type OverlayDisposer = () => void;
export type OverlayElementOptions = {
@@ -109,19 +108,19 @@ export class OverlayWindow extends ObservableReactComponent<OverlayWindowProps>
}
@observer
-export class OverlayView extends ObservableReactComponent<{}> {
+export class OverlayView extends ObservableReactComponent<object> {
// eslint-disable-next-line no-use-before-define
public static Instance: OverlayView;
@observable.shallow _elements: JSX.Element[] = [];
- constructor(props: any) {
+ constructor(props: object) {
super(props);
makeObservable(this);
if (!OverlayView.Instance) {
OverlayView.Instance = this;
- new _global.ResizeObserver(
- action((entries: any) => {
- Array.from(entries).forEach((entry: any) => {
+ new ResizeObserver(
+ action(entries => {
+ Array.from(entries).forEach(entry => {
Doc.MyOverlayDocs.forEach(docIn => {
const doc = docIn;
if (NumCast(doc.overlayX) > entry.contentRect.width - 10) {
@@ -162,17 +161,17 @@ export class OverlayView extends ObservableReactComponent<{}> {
@action
addWindow(contents: JSX.Element, options: OverlayElementOptions): OverlayDisposer {
- const remove = action(() => {
- const index = this._elements.indexOf(contents);
+ const remove = action((wincontents: JSX.Element) => {
+ const index = this._elements.indexOf(wincontents);
if (index !== -1) this._elements.splice(index, 1);
});
const wincontents = (
- <OverlayWindow onClick={remove} key={Utils.GenerateGuid()} overlayOptions={options}>
+ <OverlayWindow onClick={() => remove(wincontents)} key={Utils.GenerateGuid()} overlayOptions={options}>
{contents}
</OverlayWindow>
);
this._elements.push(wincontents);
- return remove;
+ return () => remove(wincontents);
}
removeOverlayDoc = (docs: Doc | Doc[]) => toList(docs).every(Doc.RemFromMyOverlay);
diff --git a/src/client/views/ScriptingRepl.tsx b/src/client/views/ScriptingRepl.tsx
index 1a2eb460f..2de867746 100644
--- a/src/client/views/ScriptingRepl.tsx
+++ b/src/client/views/ScriptingRepl.tsx
@@ -1,6 +1,4 @@
/* eslint-disable react/no-array-index-key */
-/* eslint-disable jsx-a11y/no-static-element-interactions */
-/* eslint-disable jsx-a11y/click-events-have-key-events */
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { action, makeObservable, observable } from 'mobx';
import { observer } from 'mobx-react';
@@ -14,21 +12,26 @@ import { OverlayView } from './OverlayView';
import './ScriptingRepl.scss';
import { DocumentIconContainer } from './nodes/DocumentIcon';
import { DocumentView } from './nodes/DocumentView';
+import { returnFalse, setupMoveUpEvents } from '../../ClientUtils';
+import { emptyFunction } from '../../Utils';
+import { ObjectField } from '../../fields/ObjectField';
+import { RefField } from '../../fields/RefField';
+import { Doc, FieldResult, FieldType, Opt } from '../../fields/Doc';
interface replValueProps {
scrollToBottom: () => void;
- value: any;
+ value: Opt<FieldResult | Promise<RefField | undefined>>;
name?: string;
}
@observer
export class ScriptingValueDisplay extends ObservableReactComponent<replValueProps> {
- constructor(props: any) {
+ constructor(props: replValueProps) {
super(props);
makeObservable(this);
}
render() {
- const val = this._props.name ? this._props.value[this._props.name] : this._props.value;
+ const val = this._props.value instanceof Doc && this._props.name ? this._props.value[this._props.name] : this._props.value;
const title = (name: string) => (
<>
{this._props.name ? <b>{this._props.name} : </b> : <> </>}
@@ -47,13 +50,14 @@ export class ScriptingValueDisplay extends ObservableReactComponent<replValuePro
}
interface ReplProps {
scrollToBottom: () => void;
- value: { [key: string]: any };
+ value: Opt<FieldResult | Promise<RefField | undefined>>;
name?: string;
}
+@observer
export class ScriptingObjectDisplay extends ObservableReactComponent<ReplProps> {
@observable collapsed = true;
- constructor(props: any) {
+ constructor(props: ReplProps) {
super(props);
makeObservable(this);
}
@@ -74,10 +78,12 @@ export class ScriptingObjectDisplay extends ObservableReactComponent<ReplProps>
{name}
</>
);
+ if (val === undefined) return '--undefined--';
+ if (val instanceof Promise) return '...Promise...';
if (this.collapsed) {
return (
<div className="scriptingObject-collapsed">
- <span onClick={this.toggle} className="scriptingObject-icon scriptingObject-iconCollapsed">
+ <span onPointerDown={e => setupMoveUpEvents(this, e, returnFalse, emptyFunction, this.toggle)} className="scriptingObject-icon scriptingObject-iconCollapsed">
<FontAwesomeIcon icon="caret-right" size="sm" />
</span>
{title} (+{Object.keys(val).length})
@@ -94,8 +100,7 @@ export class ScriptingObjectDisplay extends ObservableReactComponent<ReplProps>
</div>
<div className="scriptingObject-fields">
{Object.keys(val).map(key => (
- // eslint-disable-next-line react/jsx-props-no-spreading
- <ScriptingValueDisplay {...this._props} name={key} />
+ <ScriptingValueDisplay name={key} key={key} value={this._props.value} scrollToBottom={this._props.scrollToBottom} />
))}
</div>
</div>
@@ -104,13 +109,13 @@ export class ScriptingObjectDisplay extends ObservableReactComponent<ReplProps>
}
@observer
-export class ScriptingRepl extends ObservableReactComponent<{}> {
- constructor(props: any) {
+export class ScriptingRepl extends ObservableReactComponent<object> {
+ constructor(props: object) {
super(props);
makeObservable(this);
}
- @observable private commands: { command: string; result: any }[] = [];
+ @observable private commands: { command: string; result: unknown }[] = [];
private commandsHistory: string[] = [];
@observable private commandString: string = '';
@@ -120,13 +125,11 @@ export class ScriptingRepl extends ObservableReactComponent<{}> {
private commandsRef = React.createRef<HTMLDivElement>();
- private args: any = {};
-
getTransformer = (): Transformer => ({
transformer: context => {
const knownVars: { [name: string]: number } = {};
const usedDocuments: number[] = [];
- ScriptingGlobals.getGlobals().forEach((global: any) => {
+ ScriptingGlobals.getGlobals().forEach((global: string) => {
knownVars[global] = 1;
});
return root => {
@@ -168,7 +171,7 @@ export class ScriptingRepl extends ObservableReactComponent<{}> {
switch (e.key) {
case 'Enter': {
e.stopPropagation();
- const docGlobals: { [name: string]: any } = {};
+ const docGlobals: { [name: string]: FieldType } = {};
DocumentView.allViews().forEach((dv, i) => {
docGlobals[`d${i}`] = dv.Document;
});
@@ -176,19 +179,20 @@ export class ScriptingRepl extends ObservableReactComponent<{}> {
const script = CompileScript(this.commandString, { typecheck: false, addReturn: true, editable: true, params: { args: 'any' }, transformer: this.getTransformer(), globals });
if (!script.compiled) {
this.commands.push({ command: this.commandString, result: script.errors });
+ this.maybeScrollToBottom();
return;
}
- const result = undoable(() => script.run({ args: this.args }, () => this.commands.push({ command: this.commandString, result: e.toString() })), 'run:' + this.commandString)();
+ const result = undoable(() => script.run({}, e => this.commands.push({ command: this.commandString, result: e as string })), 'run:' + this.commandString)();
if (result.success) {
this.commands.push({ command: this.commandString, result: result.result });
this.commandsHistory.push(this.commandString);
- this.maybeScrollToBottom();
-
this.commandString = '';
this.commandBuffer = '';
this.historyIndex = -1;
}
+
+ this.maybeScrollToBottom();
break;
}
case 'ArrowUp': {
@@ -232,7 +236,7 @@ export class ScriptingRepl extends ObservableReactComponent<{}> {
private shouldScroll: boolean = false;
private maybeScrollToBottom = () => {
const ele = this.commandsRef.current;
- if (ele && ele.scrollTop === ele.scrollHeight - ele.offsetHeight) {
+ if (ele && Math.abs(Math.ceil(ele.scrollTop) - (ele.scrollHeight - ele.offsetHeight)) < 2) {
this.shouldScroll = true;
this.forceUpdate();
}
@@ -240,14 +244,14 @@ export class ScriptingRepl extends ObservableReactComponent<{}> {
private scrollToBottom() {
const ele = this.commandsRef.current;
- ele && ele.scroll({ behavior: 'auto', top: ele.scrollHeight });
+ ele?.scroll({ behavior: 'smooth', top: ele.scrollHeight });
}
- componentDidUpdate(prevProps: Readonly<{}>) {
+ componentDidUpdate(prevProps: Readonly<object>) {
super.componentDidUpdate(prevProps);
if (this.shouldScroll) {
this.shouldScroll = false;
- this.scrollToBottom();
+ setTimeout(() => this.scrollToBottom(), 0);
}
}
@@ -269,7 +273,7 @@ export class ScriptingRepl extends ObservableReactComponent<{}> {
{command || <br />}
</div>
<div className="scriptingRepl-commandResult" style={{ background: SnappingManager.userBackgroundColor }}>
- <ScriptingValueDisplay scrollToBottom={this.maybeScrollToBottom} value={result} />
+ <ScriptingValueDisplay scrollToBottom={this.maybeScrollToBottom} value={result as ObjectField | RefField} />
</div>
</div>
))}
diff --git a/src/client/views/StyleProvider.tsx b/src/client/views/StyleProvider.tsx
index 8a07a6bd7..b111904f3 100644
--- a/src/client/views/StyleProvider.tsx
+++ b/src/client/views/StyleProvider.tsx
@@ -21,7 +21,7 @@ import { undoBatch, UndoManager } from '../util/UndoManager';
import { TreeSort } from './collections/TreeSort';
import { Colors } from './global/globalEnums';
import { DocumentView, DocumentViewProps } from './nodes/DocumentView';
-import { FieldViewProps, StyleProviderFuncType } from './nodes/FieldView';
+import { FieldViewProps } from './nodes/FieldView';
import { StyleProp } from './StyleProp';
import './StyleProvider.scss';
@@ -46,7 +46,7 @@ export function styleFromLayoutString(doc: Doc, props: FieldViewProps, scale: nu
// bcz: this executes a script to convert a property expression string: { script } into a value
ScriptField.MakeFunction(expr, { this: Doc.name, scale: 'number' })?.script.run({ this: doc, scale }).result?.toString() ?? '';
divKeys.forEach((prop: string) => {
- const p = (props as any)[prop];
+ const p = (props as FieldViewProps & { [key: string]: unknown })[prop];
typeof p === 'string' && (style[prop] = p?.replace(/{([^.'][^}']+)}/g, replacer));
});
return style;
@@ -69,7 +69,7 @@ export function SetFilterOpener(func: () => void) {
// a preliminary implementation of a dash style sheet for setting rendering properties of documents nested within a Tab
//
-export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<FieldViewProps & DocumentViewProps>, property: string) : StyleProviderFuncType {
+export function DefaultStyleProvider(doc: Opt<Doc>, props: Opt<FieldViewProps & DocumentViewProps>, property: string) {
const remoteDocHeader = 'author;author_date;noMargin';
const isCaption = property.includes(':caption');
const isAnchor = property.includes(':anchor');
diff --git a/src/client/views/ViewBoxInterface.ts b/src/client/views/ViewBoxInterface.ts
index c633f34fb..dce64ab92 100644
--- a/src/client/views/ViewBoxInterface.ts
+++ b/src/client/views/ViewBoxInterface.ts
@@ -18,6 +18,9 @@ export abstract class ViewBoxInterface<P> extends ObservableReactComponent<React
abstract get Document(): Doc;
abstract get dataDoc(): Doc;
abstract get fieldKey(): string;
+ get annotationKey(): string {
+ return ''; //
+ }
promoteCollection?: () => void; // moves contents of collection to parent
updateIcon?: () => void; // updates the icon representation of the document
getAnchor?: (addAsAnnotation: boolean, pinData?: PinProps) => Doc; // returns an Anchor Doc that represents the current state of the doc's componentview (e.g., the current playhead location of a an audio/video box)
diff --git a/src/client/views/collections/CollectionCalendarView.tsx b/src/client/views/collections/CollectionCalendarView.tsx
index a08a7c7c1..9eb16917b 100644
--- a/src/client/views/collections/CollectionCalendarView.tsx
+++ b/src/client/views/collections/CollectionCalendarView.tsx
@@ -6,11 +6,11 @@ import { dateRangeStrToDates, returnTrue } from '../../../ClientUtils';
import { Doc, DocListCast } from '../../../fields/Doc';
import { StrCast } from '../../../fields/Types';
import { CollectionStackingView } from './CollectionStackingView';
-import { CollectionSubView } from './CollectionSubView';
+import { CollectionSubView, SubCollectionViewProps } from './CollectionSubView';
@observer
export class CollectionCalendarView extends CollectionSubView() {
- constructor(props: any) {
+ constructor(props: SubCollectionViewProps) {
super(props);
makeObservable(this);
}
diff --git a/src/client/views/collections/CollectionCardDeckView.tsx b/src/client/views/collections/CollectionCardDeckView.tsx
index de46180e6..28a769896 100644
--- a/src/client/views/collections/CollectionCardDeckView.tsx
+++ b/src/client/views/collections/CollectionCardDeckView.tsx
@@ -18,7 +18,7 @@ import { StyleProp } from '../StyleProp';
import { DocumentView } from '../nodes/DocumentView';
import { GPTPopup, GPTPopupMode } from '../pdf/GPTPopup/GPTPopup';
import './CollectionCardDeckView.scss';
-import { CollectionSubView } from './CollectionSubView';
+import { CollectionSubView, SubCollectionViewProps } from './CollectionSubView';
enum cardSortings {
Time = 'time',
@@ -68,7 +68,7 @@ export class CollectionCardView extends CollectionSubView() {
}
};
- constructor(props: any) {
+ constructor(props: SubCollectionViewProps) {
super(props);
makeObservable(this);
}
@@ -86,11 +86,11 @@ export class CollectionCardView extends CollectionSubView() {
}
@computed get cardSort_customField() {
- return StrCast(this.Document.cardSort_customField) as any as 'chat' | 'star' | 'idea' | 'like';
+ return StrCast(this.Document.cardSort_customField) as 'chat' | 'star' | 'idea' | 'like';
}
@computed get cardSort() {
- return StrCast(this.Document.cardSort) as any as cardSortings;
+ return StrCast(this.Document.cardSort) as cardSortings;
}
/**
* how much to scale down the contents of the view so that everything will fit
@@ -428,7 +428,6 @@ export class CollectionCardView extends CollectionSubView() {
return (
<div className="card-button-container" style={{ width: `${totalWidth}px` }}>
{numberRange(amButtons).map(i => (
- // eslint-disable-next-line jsx-a11y/control-has-associated-label
<button
key={i}
type="button"
@@ -496,8 +495,8 @@ export class CollectionCardView extends CollectionSubView() {
className="collectionCardView-outer"
ref={this.createDashEventsTarget}
style={{
- background: this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.BackgroundColor),
- color: this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.Color),
+ background: this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.BackgroundColor) as string,
+ color: this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.Color) as string,
}}>
<div
className="card-wrapper"
diff --git a/src/client/views/collections/CollectionCarouselView.tsx b/src/client/views/collections/CollectionCarouselView.tsx
index 2adad68e0..c969c39e5 100644
--- a/src/client/views/collections/CollectionCarouselView.tsx
+++ b/src/client/views/collections/CollectionCarouselView.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/jsx-props-no-spreading */
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { computed, makeObservable } from 'mobx';
@@ -18,7 +16,7 @@ import { DocumentView } from '../nodes/DocumentView';
import { FieldViewProps } from '../nodes/FieldView';
import { FormattedTextBox } from '../nodes/formattedText/FormattedTextBox';
import './CollectionCarouselView.scss';
-import { CollectionSubView } from './CollectionSubView';
+import { CollectionSubView, SubCollectionViewProps } from './CollectionSubView';
enum cardMode {
PRACTICE = 'practice',
@@ -35,7 +33,7 @@ export class CollectionCarouselView extends CollectionSubView() {
get practiceField() { return this.fieldKey + "_practice"; } // prettier-ignore
get starField() { return this.fieldKey + "_star"; } // prettier-ignore
- constructor(props: any) {
+ constructor(props: SubCollectionViewProps) {
super(props);
makeObservable(this);
}
@@ -124,7 +122,7 @@ export class CollectionCarouselView extends CollectionSubView() {
this.advance(e);
};
- captionStyleProvider = (doc: Doc | undefined, captionProps: Opt<FieldViewProps>, property: string): any => {
+ captionStyleProvider = (doc: Doc | undefined, captionProps: Opt<FieldViewProps>, property: string) => {
// first look for properties on the document in the carousel, then fallback to properties on the container
const childValue = doc?.['caption_' + property] ? this._props.styleProvider?.(doc, captionProps, property) : undefined;
return childValue ?? this._props.styleProvider?.(this.layoutDoc, captionProps, property);
@@ -161,7 +159,7 @@ export class CollectionCarouselView extends CollectionSubView() {
onDoubleClickScript={this.onContentDoubleClick}
onClickScript={this.onContentClick}
isDocumentActive={this._props.childDocumentsActive?.() ? this._props.isDocumentActive : this._props.isContentActive}
- isContentActive={this._props.childContentsActive ?? this._props.isContentActive() === false ? returnFalse : emptyFunction}
+ isContentActive={(this._props.childContentsActive ?? this._props.isContentActive() === false) ? returnFalse : emptyFunction}
hideCaptions={!!carouselShowsCaptions} // hide captions if the carousel is configured to show the captions
renderDepth={this._props.renderDepth + 1}
LayoutTemplate={this._props.childLayoutTemplate}
@@ -177,7 +175,7 @@ export class CollectionCarouselView extends CollectionSubView() {
key="caption"
onWheel={StopEvent}
style={{
- borderRadius: this._props.styleProvider?.(this.layoutDoc, captionProps, StyleProp.BorderRounding),
+ borderRadius: this._props.styleProvider?.(this.layoutDoc, captionProps, StyleProp.BorderRounding) as string,
marginRight: this.marginX,
marginLeft: this.marginX,
width: `calc(100% - ${this.marginX * 2}px)`,
@@ -218,8 +216,8 @@ export class CollectionCarouselView extends CollectionSubView() {
ref={this.createDashEventsTarget}
onContextMenu={this.specificMenu}
style={{
- background: this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.BackgroundColor),
- color: this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.Color),
+ background: this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.BackgroundColor) as string,
+ color: this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.Color) as string,
}}>
{this.content}
{/* Displays a message to the user to add more flashcards if they are in practice mode and no flashcards are there. */}
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index 5a142cc6e..e0aa79c7b 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -1,14 +1,15 @@
-/* eslint-disable @typescript-eslint/no-explicit-any */
import { action, IReactionDisposer, makeObservable, observable, reaction } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
import * as ReactDOM from 'react-dom/client';
+import ResizeObserver from 'resize-observer-polyfill';
import { addStyleSheet, addStyleSheetRule, clearStyleSheetRules, DivHeight, DivWidth, incrementTitleCopy, returnTrue, UpdateIcon } from '../../../ClientUtils';
import { Doc, DocListCast, Field, Opt } from '../../../fields/Doc';
import { AclAdmin, AclEdit, DocData } from '../../../fields/DocSymbols';
import { Id } from '../../../fields/FieldSymbols';
import { InkTool } from '../../../fields/InkField';
import { List } from '../../../fields/List';
+import { FieldType } from '../../../fields/ObjectField';
import { ImageCast, NumCast, StrCast } from '../../../fields/Types';
import { ImageField } from '../../../fields/URLField';
import { GetEffectiveAcl, inheritParentAcls, SetPropSetterCb } from '../../../fields/util';
@@ -31,17 +32,15 @@ import { UndoStack } from '../UndoStack';
import './CollectionDockingView.scss';
import { CollectionSubView, SubCollectionViewProps } from './CollectionSubView';
-const _global = (window /* browser */ || global) /* node */ as any;
-
@observer
export class CollectionDockingView extends CollectionSubView() {
- static tabClass: JSX.Element | null = null;
+ static tabClass: unknown = null;
/**
* Initialize by assigning the add split method to DocumentView and by
* configuring golden layout to render its documents using the specified React component
* @param ele - typically would be set to TabDocView
*/
- public static Init(ele: JSX.Element | null) {
+ public static Init(ele: unknown) {
this.tabClass = ele;
DocumentView.addSplit = CollectionDockingView.AddSplit;
}
@@ -54,11 +53,13 @@ export class CollectionDockingView extends CollectionSubView() {
private _flush: UndoManager.Batch | undefined;
private _unmounting = false;
private _ignoreStateChange = '';
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ private _goldenLayout: any = null;
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
public tabMap: Set<any> = new Set();
public get HasFullScreen() {
return this._goldenLayout._maximisedItem !== null;
}
- private _goldenLayout: any = null;
static _highlightStyleSheet = addStyleSheet();
constructor(props: SubCollectionViewProps) {
@@ -66,8 +67,8 @@ export class CollectionDockingView extends CollectionSubView() {
makeObservable(this);
if (this._props.renderDepth < 0) CollectionDockingView.Instance = this;
// Why is this here?
- (window as any).React = React;
- (window as any).ReactDOM = ReactDOM;
+ (window as unknown as { React: unknown }).React = React;
+ (window as unknown as { ReactDOM: unknown }).ReactDOM = ReactDOM;
DragManager.StartWindowDrag = this.StartOtherDrag;
this.Document.myTrails; // this is equivalent to having a prefetchProxy for myTrails which is needed for the My Trails button in the UI which assumes that Doc.ActiveDashboard.myTrails is legit...
}
@@ -89,10 +90,11 @@ export class CollectionDockingView extends CollectionSubView() {
};
tabItemDropped = () => DragManager.CompleteWindowDrag?.(false);
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
tabDragStart = (proxy: any, finishDrag?: (aborted: boolean) => void) => {
this._flush = this._flush ?? UndoManager.StartBatch('tab move');
- const dashDoc = proxy?._contentItem?.tab?.DashDoc as Doc;
- dashDoc && (DragManager.DocDragData = new DragManager.DocumentDragData([proxy._contentItem.tab.DashDoc]));
+ //const dashDoc = proxy?._contentItem?.tab?.DashDoc as Doc;
+ //dashDoc && (DragManager.DocDragData = new DragManager.DocumentDragData([proxy._contentItem.tab.DashDoc]));
DragManager.CompleteWindowDrag = (aborted: boolean) => {
if (aborted) {
proxy._dragListener.AbortDrag();
@@ -130,12 +132,13 @@ export class CollectionDockingView extends CollectionSubView() {
}
@undoBatch
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
public static ReplaceTab(document: Doc, mods: OpenWhereMod, stack: any, panelName: string, addToSplit?: boolean, keyValue?: boolean): boolean {
const instance = CollectionDockingView.Instance;
if (!instance) return false;
const newConfig = DashboardView.makeDocumentConfig(document, panelName, undefined, keyValue);
if (!panelName && stack) {
- const activeContentItemIndex = stack.contentItems.findIndex((item: any) => item.config === stack._activeContentItem.config);
+ const activeContentItemIndex = stack.contentItems.findIndex((item: { config: unknown }) => item.config === stack._activeContentItem.config);
const newContentItem = stack.layoutManager.createContentItem(newConfig, instance._goldenLayout);
stack.addChild(newContentItem.contentItems[0], undefined);
stack.contentItems[activeContentItemIndex].remove();
@@ -155,6 +158,7 @@ export class CollectionDockingView extends CollectionSubView() {
}
@undoBatch
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
public static ToggleSplit(doc: Doc, location: OpenWhereMod, stack?: any, panelName?: string, keyValue?: boolean) {
return Array.from(CollectionDockingView.Instance?.tabMap.keys() ?? []).findIndex(tab => tab.DashDoc === doc) !== -1 ? CollectionDockingView.CloseSplit(doc) : CollectionDockingView.AddSplit(doc, location, stack, panelName, keyValue);
}
@@ -163,6 +167,7 @@ export class CollectionDockingView extends CollectionSubView() {
// Creates a split on any side of the docking view based on the passed input pullSide and then adds the Document to the requested side
//
@action
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
public static AddSplit(document: Doc, pullSide: OpenWhereMod, stack?: any, panelName?: string, keyValue?: boolean) {
if (document?._type_collection === CollectionViewType.Docking && !keyValue) return DashboardView.openDashboard(document);
if (!CollectionDockingView.Instance) return false;
@@ -321,7 +326,7 @@ export class CollectionDockingView extends CollectionSubView() {
* @param target
* @param title
*/
- titleChanged = (target: any, value: any) => {
+ titleChanged = (target: Doc, value: FieldType) => {
const title = Field.toString(value);
if (title.startsWith('@') && !title.substring(1).match(/[()[\]@]/) && title.length > 1) {
const embedding = DocListCast(target.proto_embeddings).lastElement();
@@ -340,7 +345,7 @@ export class CollectionDockingView extends CollectionSubView() {
() => DocumentView.LightboxDoc(),
doc => setTimeout(() => !doc && this.onResize())
);
- new _global.ResizeObserver(this.onResize).observe(this._containerRef.current);
+ new ResizeObserver(this.onResize).observe(this._containerRef.current);
this._reactionDisposer = reaction(
() => StrCast(this.Document.dockingConfig),
config => {
@@ -429,7 +434,7 @@ export class CollectionDockingView extends CollectionSubView() {
@action
onPointerDown = (e: React.PointerEvent): void => {
let hitFlyout = false;
- for (let par = e.target as any; !hitFlyout && par; par = par.parentElement) {
+ for (let par = e.target as HTMLElement | null; !hitFlyout && par; par = par.parentElement) {
hitFlyout = par.className === 'dockingViewButtonSelector';
}
if (!hitFlyout) {
@@ -514,6 +519,7 @@ export class CollectionDockingView extends CollectionSubView() {
return changesMade;
};
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
tabDestroyed = (tab: any) => {
this._flush = this._flush ?? UndoManager.StartBatch('tab movement');
const dashDoc = tab.DashDoc;
@@ -531,18 +537,21 @@ export class CollectionDockingView extends CollectionSubView() {
const { fieldKey } = CollectionDockingView.Instance.props;
Doc.RemoveDocFromList(dview, fieldKey, dashDoc);
this.tabMap.delete(tab);
- tab._disposers && Object.values(tab._disposers).forEach((disposer: any) => disposer?.());
+ tab._disposers && Object.values(tab._disposers).forEach(disposer => (disposer as () => void)());
this.stateChanged();
}
};
- tabCreated = (tab: any) => {
+ tabCreated = (tab: { contentItem: { element: HTMLElement[] } }) => {
this.tabMap.add(tab);
- tab.contentItem.element[0]?.firstChild?.firstChild?.InitTab?.(tab); // have to explicitly initialize tabs that reuse contents from previous tabs (ie, when dragging a tab around a new tab is created for the old content)
+ // InitTab is added to the tab's HTMLElement in TabDocView
+ const tabdocviewContent = tab.contentItem.element[0]?.firstChild?.firstChild as unknown as { InitTab?: (tab: object) => void };
+ tabdocviewContent?.InitTab?.(tab); // have to explicitly initialize tabs that reuse contents from previous tabs (ie, when dragging a tab around a new tab is created for the old content)
};
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
stackCreated = (stackIn: any) => {
const stack = stackIn.header ? stackIn : stackIn.origin;
- stack.header?.element.on('mousedown', (e: any) => {
+ stack.header?.element.on('mousedown', (e: MouseEvent) => {
const dashboard = Doc.ActiveDashboard;
if (dashboard && e.target === stack.header?.element[0] && e.button === 2) {
dashboard.pane_count = NumCast(dashboard.pane_count) + 1;
@@ -595,7 +604,7 @@ export class CollectionDockingView extends CollectionSubView() {
})
);
- stack.element.click((e: any) => {
+ stack.element.click((e: { originalEvent: MouseEvent }) => {
if (stack.contentItems.length === 0 && Array.from(document.elementsFromPoint(e.originalEvent.x, e.originalEvent.y)).some(ele => ele?.className === 'empty-tabs-message')) {
addNewDoc();
}
@@ -633,7 +642,7 @@ export class CollectionDockingView extends CollectionSubView() {
ScriptingGlobals.add(
// eslint-disable-next-line prefer-arrow-callback
- function openInLightbox(doc: any) {
+ function openInLightbox(doc: Doc) {
CollectionDockingView.Instance?._props.addDocTab(doc, OpenWhere.lightboxAlways);
},
'opens up document in a lightbox',
@@ -641,33 +650,22 @@ ScriptingGlobals.add(
);
ScriptingGlobals.add(
// eslint-disable-next-line prefer-arrow-callback
- function openDoc(doc: any, where: OpenWhere) {
+ function openDoc(doc: Doc | string, where: OpenWhere) {
switch (where) {
case OpenWhere.addRight:
- return CollectionDockingView.AddSplit(doc, OpenWhereMod.right);
+ return doc instanceof Doc && CollectionDockingView.AddSplit(doc, OpenWhereMod.right);
case OpenWhere.overlay:
default:
- // prettier-ignore
switch (doc) {
case '<ScriptingRepl />': return OverlayView.Instance.addWindow(<ScriptingRepl />, { x: 300, y: 100, width: 200, height: 200, title: 'Scripting REPL' });
case "<UndoStack />": return OverlayView.Instance.addWindow(<UndoStack />, { x: 300, y: 100, width: 200, height: 200, title: 'Undo stack' });
- default:
- }
- Doc.AddToMyOverlay(doc);
- return true;
+ default: return doc instanceof Doc && Doc.AddToMyOverlay(doc);
+ } // prettier-ignore
}
},
'opens up document in location specified',
'(doc: any)'
);
-ScriptingGlobals.add(
- // eslint-disable-next-line prefer-arrow-callback
- function openRepl() {
- return 'openRepl';
- },
- 'opens up document in screen overlay layer',
- '(doc: any)'
-);
// eslint-disable-next-line prefer-arrow-callback
ScriptingGlobals.add(async function snapshotDashboard() {
const batch = UndoManager.StartBatch('snapshot');
diff --git a/src/client/views/collections/CollectionMasonryViewFieldRow.tsx b/src/client/views/collections/CollectionMasonryViewFieldRow.tsx
index 9a6f1e2eb..710c00841 100644
--- a/src/client/views/collections/CollectionMasonryViewFieldRow.tsx
+++ b/src/client/views/collections/CollectionMasonryViewFieldRow.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 { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { action, computed, makeObservable, observable, runInAction } from 'mobx';
import { observer } from 'mobx-react';
@@ -16,7 +13,7 @@ import { DragManager } from '../../util/DragManager';
import { CompileScript } from '../../util/Scripting';
import { SnappingManager } from '../../util/SnappingManager';
import { Transform } from '../../util/Transform';
-import { undoBatch } from '../../util/UndoManager';
+import { undoBatch, undoable } from '../../util/UndoManager';
import { EditableView } from '../EditableView';
import { ObservableReactComponent } from '../ObservableReactComponent';
import { FormattedTextBox } from '../nodes/formattedText/FormattedTextBox';
@@ -37,13 +34,13 @@ interface CMVFieldRowProps {
createDropTarget: (ele: HTMLDivElement) => void;
screenToLocalTransform: () => Transform;
setDocHeight: (key: string, thisHeight: number) => void;
- refList: any[];
+ refList: Element[];
showHandle: boolean;
}
@observer
export class CollectionMasonryViewFieldRow extends ObservableReactComponent<CMVFieldRowProps> {
- constructor(props: any) {
+ constructor(props: CMVFieldRowProps) {
super(props);
makeObservable(this);
}
@@ -73,7 +70,7 @@ export class CollectionMasonryViewFieldRow extends ObservableReactComponent<CMVF
private _dropDisposer?: DragManager.DragDropDisposer;
private _headerRef: React.RefObject<HTMLDivElement> = React.createRef();
private _contRef: React.RefObject<HTMLDivElement> = React.createRef();
- private _ele: any;
+ private _ele: HTMLDivElement | null = null;
createRowDropRef = (ele: HTMLDivElement | null) => {
this._dropDisposer?.();
@@ -118,7 +115,7 @@ export class CollectionMasonryViewFieldRow extends ObservableReactComponent<CMVF
return false;
});
- getValue = (value: string): any => {
+ getValue = (value: string) => {
const parsed = parseInt(value);
if (!isNaN(parsed)) return parsed;
if (value.toLowerCase().indexOf('true') > -1) return true;
@@ -173,7 +170,7 @@ export class CollectionMasonryViewFieldRow extends ObservableReactComponent<CMVF
return docs ? !!docs.splice(0, 0, newDoc) : this._props.parent._props.addDocument?.(newDoc) || false; // should really extend addDocument to specify insertion point (at beginning of list)
};
- deleteRow = undoBatch(
+ deleteRow = undoable(
action(() => {
this._createEmbeddingSelected = false;
const key = this._props.pivotField;
@@ -182,11 +179,12 @@ export class CollectionMasonryViewFieldRow extends ObservableReactComponent<CMVF
const index = this._props.parent.colHeaderData.indexOf(this._props.headingObject);
this._props.parent.colHeaderData.splice(index, 1);
}
- })
+ }),
+ 'delete row'
);
@action
- collapseSection = (e: any) => {
+ collapseSection = (e: PointerEvent) => {
this._createEmbeddingSelected = false;
this.toggleVisibility();
e.stopPropagation();
diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx
index b2f0280a5..7b9475590 100644
--- a/src/client/views/collections/CollectionMenu.tsx
+++ b/src/client/views/collections/CollectionMenu.tsx
@@ -1,7 +1,3 @@
-/* eslint-disable jsx-a11y/label-has-associated-control */
-/* eslint-disable jsx-a11y/no-static-element-interactions */
-/* eslint-disable jsx-a11y/click-events-have-key-events */
-/* eslint-disable jsx-a11y/control-has-associated-label */
/* eslint-disable react/no-unused-class-component-methods */
/* eslint-disable react/sort-comp */
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
diff --git a/src/client/views/collections/CollectionNoteTakingView.tsx b/src/client/views/collections/CollectionNoteTakingView.tsx
index 16c474996..e1f0a3e41 100644
--- a/src/client/views/collections/CollectionNoteTakingView.tsx
+++ b/src/client/views/collections/CollectionNoteTakingView.tsx
@@ -30,9 +30,8 @@ import { StyleProp } from '../StyleProp';
import './CollectionNoteTakingView.scss';
import { CollectionNoteTakingViewColumn } from './CollectionNoteTakingViewColumn';
import { CollectionNoteTakingViewDivider } from './CollectionNoteTakingViewDivider';
-import { CollectionSubView } from './CollectionSubView';
-
-const _global = (window /* browser */ || global) /* node */ as any;
+import { CollectionSubView, SubCollectionViewProps } from './CollectionSubView';
+import { Property } from 'csstype';
/**
* CollectionNoteTakingView is a column-based view for displaying documents. In this view, the user can (1)
@@ -52,9 +51,9 @@ export class CollectionNoteTakingView extends CollectionSubView() {
public DividerWidth = 16;
@observable docsDraggedRowCol: number[] = [];
@observable _scroll = 0;
- @observable _refList: any[] = [];
+ @observable _refList: HTMLElement[] = [];
- constructor(props: any) {
+ constructor(props: SubCollectionViewProps) {
super(props);
makeObservable(this);
}
@@ -78,7 +77,7 @@ export class CollectionNoteTakingView extends CollectionSubView() {
return colHeaderData ?? ([] as SchemaHeaderField[]);
}
@computed get headerMargin() {
- return this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.HeaderMargin);
+ return this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.HeaderMargin) as number;
}
@computed get xMargin() {
return NumCast(this.layoutDoc._xMargin, 5);
@@ -216,7 +215,7 @@ export class CollectionNoteTakingView extends CollectionSubView() {
// let's dive in and get the actual document we want to drag/move around
focusDocument = (doc: Doc, options: FocusViewOptions) => {
Doc.BrushDoc(doc);
- const found = this._mainCont && Array.from(this._mainCont.getElementsByClassName('documentView-node')).find((node: any) => node.id === doc[Id]);
+ const found = this._mainCont && Array.from(this._mainCont.getElementsByClassName('documentView-node')).find(node => node.id === doc[Id]);
if (found) {
const { top } = found.getBoundingClientRect();
const localTop = this.ScreenToLocalBoxXf().transformPoint(0, top);
@@ -295,7 +294,7 @@ export class CollectionNoteTakingView extends CollectionSubView() {
addDocument={this._props.addDocument}
moveDocument={this._props.moveDocument}
removeDocument={this._props.removeDocument}
- contentPointerEvents={StrCast(this.layoutDoc.childContentPointerEvents) as any}
+ contentPointerEvents={StrCast(this.layoutDoc.childContentPointerEvents) as Property.PointerEvents}
whenChildContentsActiveChanged={this._props.whenChildContentsActiveChanged}
addDocTab={this._props.addDocTab}
pinToPres={this._props.pinToPres}
@@ -313,14 +312,14 @@ export class CollectionNoteTakingView extends CollectionSubView() {
// how to get the width of a document. Currently returns the width of the column (minus margins)
// if a note doc. Otherwise, returns the normal width (for graphs, images, etc...)
- getDocWidth(d: Doc) {
+ getDocWidth = (d: Doc) => {
const heading = !d[this.notetakingCategoryField] ? 'unset' : Field.toString(d[this.notetakingCategoryField] as FieldType);
const existingHeader = this.colHeaderData.find(sh => sh.heading === heading);
const existingWidth = this.layoutDoc._notetaking_columns_autoSize ? 1 / (this.colHeaderData.length ?? 1) : existingHeader?.width ? existingHeader.width : 0;
const maxWidth = existingWidth > 0 ? existingWidth * this.availableWidth : this.maxColWidth;
const width = d.layout_fitWidth ? maxWidth : NumCast(d._width);
return Math.min(maxWidth - CollectionNoteTakingViewColumn.ColumnMargin, width < maxWidth ? width : maxWidth);
- }
+ };
// how to get the height of a document. Nothing special here.
getDocHeight(d?: Doc) {
@@ -364,7 +363,8 @@ export class CollectionNoteTakingView extends CollectionSubView() {
// onPointerMove is used to preview where a document will drop in a column once a drag is complete.
@action
onPointerMove = (force: boolean, ex: number, ey: number) => {
- if (this.childDocList?.includes(DragManager.DocDragData?.draggedDocuments?.lastElement() as any) || force || SnappingManager.CanEmbed) {
+ const dragDoc = DragManager.DraggedDocs?.lastElement();
+ if ((dragDoc && this.childDocList?.includes(dragDoc)) || force || SnappingManager.CanEmbed) {
// get the current docs for the column based on the mouse's x coordinate
const xCoord = this.ScreenToLocalBoxXf().transformPoint(ex, ey)[0] - 2 * this.gridGap;
const colDocs = this.getDocsFromXCoord(xCoord);
@@ -500,7 +500,7 @@ export class CollectionNoteTakingView extends CollectionSubView() {
super.onExternalDrop(
e,
{},
- undoBatch(
+ undoable(
action(docus => {
this.onPointerMove(true, e.clientX, e.clientY);
docus?.map((doc: Doc) => this.addDocument(doc));
@@ -513,7 +513,8 @@ export class CollectionNoteTakingView extends CollectionSubView() {
docs.splice(targInd, 0, newDoc);
}
this.removeDocDragHighlight();
- })
+ }),
+ 'drop into note view'
)
);
};
@@ -673,7 +674,7 @@ export class CollectionNoteTakingView extends CollectionSubView() {
return this.isContentActive() === false ? 'none' : undefined;
}
- observer = new _global.ResizeObserver(() => this._props.setHeight?.(this.headerMargin + Math.max(...this._refList.map(DivHeight))));
+ observer = new ResizeObserver(() => this._props.setHeight?.(this.headerMargin + Math.max(...this._refList.map(DivHeight))));
render() {
TraceMobx();
diff --git a/src/client/views/collections/CollectionNoteTakingViewColumn.tsx b/src/client/views/collections/CollectionNoteTakingViewColumn.tsx
index 44ab1968d..8c6a6b551 100644
--- a/src/client/views/collections/CollectionNoteTakingViewColumn.tsx
+++ b/src/client/views/collections/CollectionNoteTakingViewColumn.tsx
@@ -1,4 +1,3 @@
-/* eslint-disable jsx-a11y/control-has-associated-label */
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { action, computed, makeObservable, observable } from 'mobx';
import { observer } from 'mobx-react';
@@ -16,7 +15,7 @@ import { SnappingManager } from '../../util/SnappingManager';
import { Transform } from '../../util/Transform';
import { undoBatch, undoable } from '../../util/UndoManager';
import { ContextMenu } from '../ContextMenu';
-import { EditableView } from '../EditableView';
+import { EditableProps, EditableView } from '../EditableView';
import { ObservableReactComponent } from '../ObservableReactComponent';
import { FormattedTextBox } from '../nodes/formattedText/FormattedTextBox';
import './CollectionNoteTakingView.scss';
@@ -24,7 +23,7 @@ import './CollectionNoteTakingView.scss';
interface CSVFieldColumnProps {
Document: Doc;
TemplateDataDocument: Opt<Doc>;
- backgroundColor?: (() => string) | undefined;
+ backgroundColor?: () => string | undefined;
docList: Doc[];
heading: string;
pivotField: string;
@@ -35,15 +34,15 @@ interface CSVFieldColumnProps {
yMargin: number;
numGroupColumns: number;
gridGap: number;
- headings: () => object[];
+ headings: () => [SchemaHeaderField, Doc[]][];
select: (ctrlPressed: boolean) => void;
isContentActive: () => boolean | undefined;
renderChildren: (docs: Doc[]) => JSX.Element[];
addDocument: (doc: Doc | Doc[]) => boolean;
createDropTarget: (ele: HTMLDivElement) => void;
screenToLocalTransform: () => Transform;
- refList: any[];
- editableViewProps: () => any;
+ refList: HTMLElement[];
+ editableViewProps: () => EditableProps;
resizeColumns: (headers: SchemaHeaderField[]) => boolean;
maxColWidth: number;
dividerWidth: number;
@@ -103,7 +102,7 @@ export class CollectionNoteTakingViewColumn extends ObservableReactComponent<CSV
return true;
};
- getValue = (value: string): any => {
+ getValue = (value: string) => {
const parsed = parseInt(value);
if (!isNaN(parsed)) return parsed;
if (value.toLowerCase().indexOf('true') > -1) return true;
@@ -272,7 +271,7 @@ export class CollectionNoteTakingViewColumn extends ObservableReactComponent<CSV
style={{
width: this.columnWidth,
background: this._hover && SnappingManager.IsDragging ? '#b4b4b4' : 'inherit',
- marginLeft: this._props.headings().findIndex((h: any) => h[0] === this._props.headingObject) === 0 ? NumCast(this._props.Document.xMargin) : 0,
+ marginLeft: this._props.headings().findIndex(h => h[0] === this._props.headingObject) === 0 ? NumCast(this._props.Document.xMargin) : 0,
}}>
<div className="collectionNoteTakingViewFieldColumn" key={this._heading} ref={this.createColumnDropRef}>
{this.innards}
diff --git a/src/client/views/collections/CollectionPileView.tsx b/src/client/views/collections/CollectionPileView.tsx
index 5b3f625db..eea128803 100644
--- a/src/client/views/collections/CollectionPileView.tsx
+++ b/src/client/views/collections/CollectionPileView.tsx
@@ -1,10 +1,8 @@
-/* eslint-disable jsx-a11y/no-static-element-interactions */
-/* eslint-disable jsx-a11y/click-events-have-key-events */
import { action, computed, IReactionDisposer, makeObservable } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
import { returnFalse, setupMoveUpEvents } from '../../../ClientUtils';
-import { Doc, DocListCast } from '../../../fields/Doc';
+import { Doc, DocListCast, FieldResult } from '../../../fields/Doc';
import { ScriptField } from '../../../fields/ScriptField';
import { NumCast, StrCast, toList } from '../../../fields/Types';
import { emptyFunction } from '../../../Utils';
@@ -15,15 +13,15 @@ import { OpenWhere } from '../nodes/OpenWhere';
import { computePassLayout, computeStarburstLayout } from './collectionFreeForm';
import { CollectionFreeFormView } from './collectionFreeForm/CollectionFreeFormView';
import './CollectionPileView.scss';
-import { CollectionSubView } from './CollectionSubView';
+import { CollectionSubView, SubCollectionViewProps } from './CollectionSubView';
import { DocumentView } from '../nodes/DocumentView';
@observer
export class CollectionPileView extends CollectionSubView() {
- _originalChrome: any = '';
+ _originalChrome: FieldResult = '';
_disposers: { [name: string]: IReactionDisposer } = {};
- constructor(props: any) {
+ constructor(props: SubCollectionViewProps) {
super(props);
makeObservable(this);
}
diff --git a/src/client/views/collections/CollectionStackedTimeline.tsx b/src/client/views/collections/CollectionStackedTimeline.tsx
index b03f0cffa..08f3f3d65 100644
--- a/src/client/views/collections/CollectionStackedTimeline.tsx
+++ b/src/client/views/collections/CollectionStackedTimeline.tsx
@@ -1,8 +1,5 @@
/* eslint-disable react/jsx-props-no-spreading */
-/* eslint-disable jsx-a11y/alt-text */
/* eslint-disable no-use-before-define */
-/* eslint-disable jsx-a11y/no-static-element-interactions */
-/* eslint-disable jsx-a11y/click-events-have-key-events */
import { action, computed, IReactionDisposer, makeObservable, observable, reaction, runInAction } from 'mobx';
import { observer } from 'mobx-react';
import { computedFn } from 'mobx-utils';
@@ -34,7 +31,7 @@ import { LabelBox } from '../nodes/LabelBox';
import { OpenWhere } from '../nodes/OpenWhere';
import { ObservableReactComponent } from '../ObservableReactComponent';
import './CollectionStackedTimeline.scss';
-import { CollectionSubView } from './CollectionSubView';
+import { CollectionSubView, SubCollectionViewProps } from './CollectionSubView';
export type CollectionStackedTimelineProps = {
Play: () => void;
@@ -72,7 +69,7 @@ export class CollectionStackedTimeline extends CollectionSubView<CollectionStack
);
this.SelectingRegions.clear();
}
- constructor(props: any) {
+ constructor(props: SubCollectionViewProps & CollectionStackedTimelineProps) {
super(props);
makeObservable(this);
}
@@ -182,7 +179,7 @@ export class CollectionStackedTimeline extends CollectionSubView<CollectionStack
});
anchorStart = (anchor: Doc) => NumCast(anchor._timecodeToShow, NumCast(anchor[this._props.startTag]));
- anchorEnd = (anchor: Doc, val: any = null) => NumCast(anchor._timecodeToHide, NumCast(anchor[this._props.endTag], val) ?? null);
+ anchorEnd = (anchor: Doc, val?: number) => NumCast(anchor._timecodeToHide, NumCast(anchor[this._props.endTag], val) ?? null);
// converts screen pixel offset to time
// prettier-ignore
@@ -192,13 +189,13 @@ export class CollectionStackedTimeline extends CollectionSubView<CollectionStack
@computed get rangeClick() {
// prettier-ignore
return ScriptField.MakeFunction('stackedTimeline.clickAnchor(this, clientX)',
- { stackedTimeline: 'any', clientX: 'number' }, { stackedTimeline: this as any }
+ { stackedTimeline: 'any', clientX: 'number' }, { stackedTimeline: 'string' /* should be CollectionStackedTimeline */ }
)!;
}
@computed get rangePlay() {
// prettier-ignore
return ScriptField.MakeFunction('stackedTimeline.playOnClick(this, clientX)',
- { stackedTimeline: 'any', clientX: 'number' }, { stackedTimeline: this as any })!;
+ { stackedTimeline: 'any', clientX: 'number' }, { stackedTimeline: 'string' /* should be CollectionStackedTimeline */})!;
}
rangeClickScript = () => this.rangeClick;
rangePlayScript = () => this.rangePlay;
@@ -426,7 +423,7 @@ export class CollectionStackedTimeline extends CollectionSubView<CollectionStack
const anchor =
docAnchor ??
Docs.Create.LabelDocument({
- title: ComputedField.MakeFunction(`this["${endTag}"] ? "#" + formatToTime(this["${startTag}"]) + "-" + formatToTime(this["${endTag}"]) : "#" + formatToTime(this["${startTag}"])`) as any,
+ title: ComputedField.MakeFunction(`this["${endTag}"] ? "#" + formatToTime(this["${startTag}"]) + "-" + formatToTime(this["${endTag}"]) : "#" + formatToTime(this["${startTag}"])`) as unknown as string, // title can take a function or a string
_label_minFontSize: 12,
_label_maxFontSize: 24,
_dragOnlyWithinContainer: true,
@@ -777,8 +774,8 @@ class StackedTimelineAnchor extends ObservableReactComponent<StackedTimelineAnch
@action
onAnchorDown = (e: React.PointerEvent, anchor: Doc, left: boolean): void => {
const newTime = (timeDownEv: PointerEvent) => {
- const rect = (timeDownEv.target as any).getBoundingClientRect();
- return this._props.toTimeline(timeDownEv.clientX - rect.x, rect.width);
+ const rect = (timeDownEv.target as HTMLElement).getBoundingClientRect?.();
+ return !rect ? 0 : this._props.toTimeline(timeDownEv.clientX - rect.x, rect.width);
};
const changeAnchor = (time: number | undefined) => {
const timelineOnly = Cast(anchor[this._props.startTag], 'number', null) !== undefined;
@@ -892,7 +889,7 @@ class StackedTimelineAnchor extends ObservableReactComponent<StackedTimelineAnch
}
}
// eslint-disable-next-line prefer-arrow-callback
-ScriptingGlobals.add(function formatToTime(time: number): any {
+ScriptingGlobals.add(function formatToTime(time: number): string {
return formatTime(time);
});
// eslint-disable-next-line prefer-arrow-callback
diff --git a/src/client/views/collections/CollectionStackingView.tsx b/src/client/views/collections/CollectionStackingView.tsx
index 56d2a6c9c..03ade6579 100644
--- a/src/client/views/collections/CollectionStackingView.tsx
+++ b/src/client/views/collections/CollectionStackingView.tsx
@@ -1,6 +1,5 @@
/* eslint-disable react/jsx-props-no-spreading */
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
-// eslint-disable-next-line import/no-extraneous-dependencies
import * as CSS from 'csstype';
import { action, computed, IReactionDisposer, makeObservable, observable, ObservableMap, reaction, runInAction } from 'mobx';
import { observer } from 'mobx-react';
@@ -34,9 +33,7 @@ import { StyleProp } from '../StyleProp';
import { CollectionMasonryViewFieldRow } from './CollectionMasonryViewFieldRow';
import './CollectionStackingView.scss';
import { CollectionStackingViewFieldColumn } from './CollectionStackingViewFieldColumn';
-import { CollectionSubView } from './CollectionSubView';
-
-const _global = (window /* browser */ || global) /* node */ as any;
+import { CollectionSubView, SubCollectionViewProps } from './CollectionSubView';
export type collectionStackingViewProps = {
sortFunc?: (a: Doc, b: Doc) => number;
@@ -57,8 +54,9 @@ export class CollectionStackingView extends CollectionSubView<Partial<collection
_docXfs: { height: () => number; width: () => number; stackedDocTransform: () => Transform }[] = [];
// Doesn't look like this field is being used anywhere. Obsolete?
_columnStart: number = 0;
+ _oldWheel: HTMLElement | null = null;
- @observable _refList: any[] = [];
+ @observable _refList: HTMLElement[] = [];
// map of node headers to their heights. Used in Masonry
@observable _heightMap = new Map<string, number>();
// Assuming that this is the current css cursor style
@@ -85,7 +83,7 @@ export class CollectionStackingView extends CollectionSubView<Partial<collection
}
// how much margin we give the header
@computed get headerMargin() {
- return this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.HeaderMargin);
+ return this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.HeaderMargin) as number;
}
@computed get xMargin() {
return NumCast(this.layoutDoc._xMargin, Math.max(3, 0.05 * this._props.PanelWidth()));
@@ -118,7 +116,7 @@ export class CollectionStackingView extends CollectionSubView<Partial<collection
return this._props.PanelWidth() - this.gridGap;
}
- constructor(props: any) {
+ constructor(props: SubCollectionViewProps) {
super(props);
makeObservable(this);
if (this.colHeaderData === undefined) {
@@ -260,7 +258,7 @@ export class CollectionStackingView extends CollectionSubView<Partial<collection
focusDocument = (doc: Doc, options: FocusViewOptions) => {
Doc.BrushDoc(doc);
- const found = this._mainCont && Array.from(this._mainCont.getElementsByClassName('documentView-node')).find((node: any) => node.id === doc[Id]);
+ const found = this._mainCont && Array.from(this._mainCont.getElementsByClassName('documentView-node')).find(node => node.id === doc[Id]);
if (found) {
const { top } = found.getBoundingClientRect();
const localTop = this.ScreenToLocalBoxXf().transformPoint(0, top);
@@ -344,7 +342,7 @@ export class CollectionStackingView extends CollectionSubView<Partial<collection
LayoutTemplateString={this._props.childLayoutString}
NativeWidth={this._props.childIgnoreNativeSize ? returnZero : this._props.childLayoutFitWidth?.(doc) || (this.childFitWidth(doc) && !Doc.NativeWidth(doc)) ? width : undefined} // explicitly ignore nativeWidth/height if childIgnoreNativeSize is set- used by PresBox
NativeHeight={this._props.childIgnoreNativeSize ? returnZero : this._props.childLayoutFitWidth?.(doc) || (this.childFitWidth(doc) && !Doc.NativeHeight(doc)) ? height : undefined}
- dontCenter={this._props.childIgnoreNativeSize ? 'xy' : (StrCast(this.layoutDoc.layout_dontCenter) as any)}
+ dontCenter={this._props.childIgnoreNativeSize ? 'xy' : (StrCast(this.layoutDoc.layout_dontCenter) as 'x' | 'y' | 'xy')}
dontRegisterView={BoolCast(this.layoutDoc.childDontRegisterViews, this._props.dontRegisterView)} // used to be true if DataDoc existed, but template textboxes won't layout_autoHeight resize if dontRegisterView is set, but they need to.
rootSelected={this.rootSelected}
showTitle={this._props.childlayout_showTitle}
@@ -363,7 +361,7 @@ export class CollectionStackingView extends CollectionSubView<Partial<collection
addDocument={this._props.addDocument}
moveDocument={this._props.moveDocument}
removeDocument={this._props.removeDocument}
- contentPointerEvents={StrCast(this.layoutDoc.childContentPointerEvents) as any}
+ contentPointerEvents={StrCast(this.layoutDoc.childContentPointerEvents) as CSS.Property.PointerEvents | undefined}
whenChildContentsActiveChanged={this._props.whenChildContentsActiveChanged}
addDocTab={this._props.addDocTab}
pinToPres={this._props.pinToPres}
@@ -623,7 +621,7 @@ export class CollectionStackingView extends CollectionSubView<Partial<collection
if (!e.isPropagationStopped()) {
const cm = ContextMenu.Instance;
const options = cm.findByDescription('Options...');
- const optionItems: ContextMenuProps[] = options && 'subitems' in options ? options.subitems : [];
+ const optionItems: ContextMenuProps[] = options?.subitems ?? [];
optionItems.push({ description: `${this.layoutDoc._columnsFill ? 'Variable Size' : 'Autosize'} Column`, event: () => { this.layoutDoc._columnsFill = !this.layoutDoc._columnsFill; }, icon: 'plus' }); // prettier-ignore
optionItems.push({ description: `${this.layoutDoc._layout_autoHeight ? 'Variable Height' : 'Auto Height'}`, event: () => { this.layoutDoc._layout_autoHeight = !this.layoutDoc._layout_autoHeight; }, icon: 'plus' }); // prettier-ignore
optionItems.push({ description: 'Clear All', event: () => { this.dataDoc[this.fieldKey ?? 'data'] = new List([]); } , icon: 'times' }); // prettier-ignore
@@ -688,10 +686,9 @@ export class CollectionStackingView extends CollectionSubView<Partial<collection
return this._props.isContentActive() === false ? 'none' : undefined;
}
- observer = new _global.ResizeObserver(() => this._props.setHeight?.(this.headerMargin + (this.isStackingView ? Math.max(...this._refList.map(DivHeight)) : this._refList.reduce((p, r) => p + DivHeight(r), 0))));
+ observer = new ResizeObserver(() => this._props.setHeight?.(this.headerMargin + (this.isStackingView ? Math.max(...this._refList.map(DivHeight)) : this._refList.reduce((p, r) => p + DivHeight(r), 0))));
onPassiveWheel = (e: WheelEvent) => e.stopPropagation();
- _oldWheel: any;
render() {
TraceMobx();
const editableViewProps = {
@@ -722,8 +719,8 @@ export class CollectionStackingView extends CollectionSubView<Partial<collection
}}
style={{
overflowY: this.isContentActive() ? 'auto' : 'hidden',
- background: this._props.styleProvider?.(this.Document, this._props, StyleProp.BackgroundColor),
- pointerEvents: (this._props.pointerEvents?.() as any) ?? this.backgroundEvents,
+ background: this._props.styleProvider?.(this.Document, this._props, StyleProp.BackgroundColor) as string,
+ pointerEvents: this._props.pointerEvents?.() ?? this.backgroundEvents,
}}
onScroll={action(e => {
this._scroll = e.currentTarget.scrollTop;
diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx
index b7169ece0..5782d407e 100644
--- a/src/client/views/collections/CollectionSubView.tsx
+++ b/src/client/views/collections/CollectionSubView.tsx
@@ -22,7 +22,7 @@ import { DragManager } from '../../util/DragManager';
import { dropActionType } from '../../util/DropActionTypes';
import { ImageUtils } from '../../util/Import & Export/ImageUtils';
import { SnappingManager } from '../../util/SnappingManager';
-import { UndoManager, undoBatch } from '../../util/UndoManager';
+import { UndoManager } from '../../util/UndoManager';
import { ViewBoxBaseComponent } from '../DocComponent';
import { FieldViewProps } from '../nodes/FieldView';
import { DocumentView } from '../nodes/DocumentView';
@@ -227,7 +227,6 @@ export function CollectionSubView<X>() {
}
}
- @undoBatch
// eslint-disable-next-line @typescript-eslint/no-unused-vars
protected onGesture(e: Event, ge: GestureUtils.GestureEvent) {}
@@ -294,7 +293,6 @@ export function CollectionSubView<X>() {
return false;
}
- @undoBatch
protected async onExternalDrop(e: React.DragEvent, options: DocumentOptions, completed?: (docs: Doc[]) => void) {
if (e.ctrlKey) {
e.stopPropagation(); // bcz: this is a hack to stop propagation when dropping an image on a text document with shift+ctrl
@@ -386,7 +384,7 @@ export function CollectionSubView<X>() {
addDocument(htmlDoc);
if (srcWeb) {
const iframe = DocumentView.Selected()[0].ContentDiv?.getElementsByTagName('iframe')?.[0];
- const focusNode = iframe?.contentDocument?.getSelection()?.focusNode as any;
+ const focusNode = iframe?.contentDocument?.getSelection()?.focusNode;
if (focusNode) {
const anchor = srcWeb?.ComponentView?.getAnchor?.(true);
anchor && DocUtils.MakeLink(htmlDoc, anchor, {});
@@ -465,23 +463,6 @@ export function CollectionSubView<X>() {
if (item.kind === 'file') {
const file = item.getAsFile();
file?.type && files.push(file);
-
- file?.type === 'application/json' &&
- ClientUtils.readUploadedFileAsText(file).then(result => {
- const json = JSON.parse(result as string);
- addDocument(
- Docs.Create.TreeDocument(
- json['rectangular-puzzle'].crossword.clues[0].clue.map((c: any) => {
- const label = Docs.Create.LabelDocument({ title: c['#text'], _width: 120, _height: 20 });
- const proto = Doc.GetProto(label);
- proto._width = 120;
- proto._height = 20;
- return proto;
- }),
- { _width: 150, _height: 600, title: 'across', backgroundColor: 'white', _createDocOnCR: true }
- )
- );
- });
}
}
this.slowLoadDocuments(files, options, generatedDocuments, text, completed, addDocument).then(batch.end);
diff --git a/src/client/views/collections/CollectionTimeView.tsx b/src/client/views/collections/CollectionTimeView.tsx
index 0369e4a2a..8a24db330 100644
--- a/src/client/views/collections/CollectionTimeView.tsx
+++ b/src/client/views/collections/CollectionTimeView.tsx
@@ -1,5 +1,3 @@
-/* eslint-disable jsx-a11y/no-static-element-interactions */
-/* eslint-disable jsx-a11y/click-events-have-key-events */
import { action, computed, makeObservable, observable, runInAction } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
@@ -18,7 +16,7 @@ import { ContextMenuProps } from '../ContextMenuItem';
import { FieldsDropdown } from '../FieldsDropdown';
import { PinDocView } from '../PinFuncs';
import { DocumentView } from '../nodes/DocumentView';
-import { CollectionSubView } from './CollectionSubView';
+import { CollectionSubView, SubCollectionViewProps } from './CollectionSubView';
import './CollectionTimeView.scss';
import { ViewDefBounds, computePivotLayout, computeTimelineLayout } from './collectionFreeForm/CollectionFreeFormLayoutEngines';
import { CollectionFreeFormView } from './collectionFreeForm/CollectionFreeFormView';
@@ -32,7 +30,7 @@ export class CollectionTimeView extends CollectionSubView() {
@observable _viewDefDivClick: Opt<ScriptField> = undefined;
@observable _focusPivotField: Opt<string> = undefined;
- constructor(props: any) {
+ constructor(props: SubCollectionViewProps) {
super(props);
makeObservable(this);
}
@@ -51,7 +49,7 @@ export class CollectionTimeView extends CollectionSubView() {
getAnchor = (addAsAnnotation: boolean) => {
const anchor = Docs.Create.ConfigDocument({
- title: ComputedField.MakeFunction(`"${this.pivotField}"])`) as any,
+ title: ComputedField.MakeFunction(`"${this.pivotField}"])`) as unknown as string, // title can take a functiono or a string
annotationOn: this.Document,
});
PinDocView(anchor, { pinData: { type_collection: true, pivot: true, filters: true } }, this.Document);
diff --git a/src/client/views/collections/CollectionTreeView.tsx b/src/client/views/collections/CollectionTreeView.tsx
index 285598600..ff316cfbd 100644
--- a/src/client/views/collections/CollectionTreeView.tsx
+++ b/src/client/views/collections/CollectionTreeView.tsx
@@ -1,8 +1,7 @@
-/* eslint-disable jsx-a11y/no-static-element-interactions */
-/* eslint-disable jsx-a11y/click-events-have-key-events */
-import { action, computed, IReactionDisposer, makeObservable, observable, reaction } from 'mobx';
+import { action, computed, IReactionDisposer, makeObservable, observable, reaction, runInAction } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
+import ResizeObserver from 'resize-observer-polyfill';
import { DivHeight, returnAll, returnEmptyDoclist, returnEmptyFilter, returnFalse, returnNone, returnOne, returnTrue, returnZero } from '../../../ClientUtils';
import { Doc, DocListCast, Opt, StrListCast } from '../../../fields/Doc';
import { DocData } from '../../../fields/DocSymbols';
@@ -19,7 +18,7 @@ import { dropActionType } from '../../util/DropActionTypes';
import { ScriptingGlobals } from '../../util/ScriptingGlobals';
import { SnappingManager } from '../../util/SnappingManager';
import { Transform } from '../../util/Transform';
-import { undoBatch, UndoManager } from '../../util/UndoManager';
+import { undoable, undoBatch, UndoManager } from '../../util/UndoManager';
import { ContextMenu } from '../ContextMenu';
import { ContextMenuProps } from '../ContextMenuItem';
import { EditableView } from '../EditableView';
@@ -27,13 +26,11 @@ import { DocumentView } from '../nodes/DocumentView';
import { FormattedTextBox } from '../nodes/formattedText/FormattedTextBox';
import { StyleProp } from '../StyleProp';
import { CollectionFreeFormView } from './collectionFreeForm';
-import { CollectionSubView } from './CollectionSubView';
+import { CollectionSubView, SubCollectionViewProps } from './CollectionSubView';
import './CollectionTreeView.scss';
import { TreeViewType } from './CollectionTreeViewType';
import { TreeView } from './TreeView';
-const _global = (window /* browser */ || global) /* node */ as any;
-
export type collectionTreeViewProps = {
treeViewExpandedView?: 'fields' | 'layout' | 'links' | 'data';
treeViewOpen?: boolean;
@@ -55,10 +52,10 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
private _titleRef?: HTMLDivElement | HTMLInputElement | null;
private _disposers: { [name: string]: IReactionDisposer } = {};
private _isDisposing = false; // notes that instance is in process of being disposed
- private refList: Set<any> = new Set(); // list of tree view items to monitor for height changes
- private observer: any; // observer for monitoring tree view items.
+ private refList: Set<HTMLElement> = new Set(); // list of tree view items to monitor for height changes
+ private observer: ResizeObserver | undefined; // observer for monitoring tree view items.
- constructor(props: any) {
+ constructor(props: SubCollectionViewProps & collectionTreeViewProps) {
super(props);
makeObservable(this);
}
@@ -113,14 +110,14 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
!this._props.dontRegisterView && this._props.setHeight?.(bodyHeight + titleHeight);
}
};
- unobserveHeight = (ref: any) => {
+ unobserveHeight = (ref: HTMLElement) => {
this.refList.delete(ref);
this.layoutDoc.layout_autoHeight && this.computeHeight();
};
- observeHeight = (ref: any) => {
+ observeHeight = (ref: HTMLElement) => {
if (ref) {
this.refList.add(ref);
- this.observer = new _global.ResizeObserver(() => {
+ this.observer = new ResizeObserver(() => {
if (this.layoutDoc.layout_autoHeight && ref && this.refList.size && !SnappingManager.IsDragging) {
this.computeHeight();
}
@@ -216,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' in existingOnClick ? 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' });
}
@@ -234,11 +231,11 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
maxHeight={72}
height="auto"
GetValue={() => StrCast(this.dataDoc.title)}
- SetValue={undoBatch((value: string, shift: boolean, enter: boolean) => {
+ SetValue={undoable((value: string, shift: boolean, enter: boolean) => {
if (enter && this.Document.treeView_Type === TreeViewType.outline) this.makeTextCollection(this.treeChildren);
this.dataDoc.title = value;
return true;
- })}
+ }, 'set doc title')}
/>
);
}
@@ -285,7 +282,7 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
@observable _renderCount = 1;
@computed get treeViewElements() {
TraceMobx();
- const dragAction = StrCast(this.Document.childDragAction) as any as dropActionType;
+ const dragAction = StrCast(this.Document.childDragAction) as dropActionType;
const treeAddDoc = (doc: Doc | Doc[], relativeTo?: Doc, before?: boolean) => this.addDoc(doc, relativeTo, before);
const moveDoc = (d: Doc | Doc[], target: Doc | undefined, addDoc: (doc: Doc | Doc[]) => boolean) => this._props.moveDocument?.(d, target, addDoc) || false;
if (this._renderCount < this.treeChildren.length)
@@ -333,9 +330,11 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
return this.dataDoc === null ? null : (
<div
className="collectionTreeView-titleBar"
- ref={action((r: any) => {
- (this._titleRef = r) && (this._titleHeight = r.getBoundingClientRect().height * this.ScreenToLocalBoxXf().Scale);
- })}
+ ref={r =>
+ runInAction(() => {
+ (this._titleRef = r) && (this._titleHeight = r.getBoundingClientRect().height * this.ScreenToLocalBoxXf().Scale);
+ })
+ }
key={this.Document[Id]}
style={!this.outlineMode ? { marginLeft: this.marginX(), paddingTop: this.marginTop() } : {}}>
{this.outlineMode ? this.documentTitle : this.editableTitle}
@@ -410,8 +409,8 @@ export class CollectionTreeView extends CollectionSubView<Partial<collectionTree
@observable _headerHeight = 0;
@computed get content() {
- const background = () => this._props.styleProvider?.(this.Document, this._props, StyleProp.BackgroundColor);
- const color = () => this._props.styleProvider?.(this.Document, this._props, StyleProp.Color);
+ const background = () => this._props.styleProvider?.(this.Document, this._props, StyleProp.BackgroundColor) as string;
+ const color = () => this._props.styleProvider?.(this.Document, this._props, StyleProp.Color) as string;
const pointerEvents = () => (this._props.isContentActive() === false ? 'none' : undefined);
const titleBar = this._props.treeViewHideTitle || this.Document.treeView_HideTitle ? null : this.titleBar;
return (
diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx
index f50f7394b..ee5c4afc0 100644
--- a/src/client/views/collections/TabDocView.tsx
+++ b/src/client/views/collections/TabDocView.tsx
@@ -6,6 +6,7 @@ import { IReactionDisposer, ObservableSet, action, computed, makeObservable, obs
import { observer } from 'mobx-react';
import * as React from 'react';
import * as ReactDOM from 'react-dom/client';
+import ResizeObserver from 'resize-observer-polyfill';
import { ClientUtils, DashColor, lightOrDark, returnEmptyDoclist, returnFalse, returnTrue, setupMoveUpEvents, simulateMouseClick } from '../../../ClientUtils';
import { emptyFunction } from '../../../Utils';
import { Doc, Opt } from '../../../fields/Doc';
@@ -41,8 +42,6 @@ import { CollectionView } from './CollectionView';
import './TabDocView.scss';
import { CollectionFreeFormView } from './collectionFreeForm/CollectionFreeFormView';
-const _global = (window /* browser */ || global) /* node */ as any;
-
interface TabMinimapViewProps {
document: Doc;
tabView: () => DocumentView | undefined;
@@ -183,6 +182,7 @@ export class TabMinimapView extends ObservableReactComponent<TabMinimapViewProps
interface TabDocViewProps {
documentId: FieldId;
keyValue?: boolean;
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
glContainer: any;
}
@observer
@@ -327,10 +327,12 @@ export class TabDocView extends ObservableReactComponent<TabDocViewProps> {
get view() {
return this._view;
}
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
_lastTab: any;
_lastView: DocumentView | undefined;
@action
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
init = (tab: any, doc: Opt<Doc>) => {
if (tab.contentItem === tab.header.parent.getActiveContentItem()) this._activated = true;
if (tab.DashDoc !== doc && doc && tab.contentItem?.config.type !== 'stack') {
@@ -357,10 +359,11 @@ export class TabDocView extends ObservableReactComponent<TabDocViewProps> {
titleEle.size = StrCast(doc.title).length + 3;
titleEle.value = doc.title;
titleEle.onkeydown = (e: KeyboardEvent) => e.stopPropagation();
- titleEle.onchange = (e: any) => {
+ titleEle.onchange = (e: InputEvent) => {
undoable(() => {
- titleEle.size = e.currentTarget.value.length + 3;
- doc[DocData].title = e.currentTarget.value;
+ const target = e.currentTarget as unknown as { value: string };
+ titleEle.size = target?.value.length + 3;
+ doc[DocData].title = target?.value ?? '';
}, 'edit tab title')();
};
@@ -449,8 +452,8 @@ export class TabDocView extends ObservableReactComponent<TabDocViewProps> {
};
// select the tab document when the tab is directly clicked and activate the tab whenver the tab document is selected
- titleEle.onpointerdown = action((e: any) => {
- if (e.target.className !== 'lm_iconWrap') {
+ titleEle.onpointerdown = action((e: PointerEvent) => {
+ if ((e.target as HTMLElement)?.className !== 'lm_iconWrap') {
if (this.view) DocumentView.SelectView(this.view, false);
else this._activated = true;
if (Date.now() - titleEle.lastClick < 1000) titleEle.select();
@@ -482,7 +485,7 @@ export class TabDocView extends ObservableReactComponent<TabDocViewProps> {
tab.closeElement
.off('click') // unbind the current click handler
.click(() => {
- Object.values(tab._disposers).forEach((disposer: any) => disposer?.());
+ Object.values(tab._disposers).forEach(disposer => (disposer as () => void)());
DocumentView.DeselectAll();
UndoManager.RunInBatch(() => tab.contentItem.remove(), 'delete tab');
});
@@ -490,8 +493,8 @@ export class TabDocView extends ObservableReactComponent<TabDocViewProps> {
};
componentDidMount() {
- new _global.ResizeObserver(
- action((entries: any) => {
+ new ResizeObserver(
+ action(entries => {
// eslint-disable-next-line no-restricted-syntax
for (const entry of entries) {
this._panelWidth = entry.contentRect.width;
@@ -524,6 +527,7 @@ export class TabDocView extends ObservableReactComponent<TabDocViewProps> {
public static DontSelectOnActivate = 'dontSelectOnActivate';
@action.bound
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
private onActiveContentItemChanged(contentItem: any) {
if (!contentItem || (this.stack === contentItem.parent && ((contentItem?.tab === this.tab && !this._isActive) || (contentItem?.tab !== this.tab && this._isActive)))) {
this._activated = this._isActive = !contentItem || contentItem?.tab === this.tab;
@@ -650,13 +654,13 @@ export class TabDocView extends ObservableReactComponent<TabDocViewProps> {
this._view && DocumentView.removeView(this._view);
}
this._lastTab = this.tab;
- (this._mainCont as any).InitTab = (tab: any) => this.init(tab, this._document);
+ (this._mainCont as { InitTab?: (tab: object) => void }).InitTab = (tab: object) => this.init(tab, this._document);
DocServer.GetRefField(this._props.documentId).then(
action(doc => {
doc instanceof Doc && (this._document = doc) && this.tab && this.init(this.tab, this._document);
})
);
- new _global.ResizeObserver(action(() => this._forceInvalidateScreenToLocal++)).observe(ref);
+ ref && new ResizeObserver(action(() => this._forceInvalidateScreenToLocal++)).observe(ref);
}
}}>
{this.docView}
diff --git a/src/client/views/collections/TreeView.tsx b/src/client/views/collections/TreeView.tsx
index 161d93788..54053d038 100644
--- a/src/client/views/collections/TreeView.tsx
+++ b/src/client/views/collections/TreeView.tsx
@@ -1,10 +1,7 @@
-/* eslint-disable jsx-a11y/no-static-element-interactions */
-/* eslint-disable jsx-a11y/no-noninteractive-element-interactions */
-/* eslint-disable jsx-a11y/click-events-have-key-events */
import { IconProp } from '@fortawesome/fontawesome-svg-core';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { IconButton, Size } from 'browndash-components';
-import { IReactionDisposer, action, computed, makeObservable, observable, reaction } from 'mobx';
+import { IReactionDisposer, action, computed, makeObservable, observable, reaction, runInAction } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
import { ClientUtils, lightOrDark, return18, returnEmptyDoclist, returnEmptyFilter, returnEmptyString, returnFalse, returnTrue, returnZero, setupMoveUpEvents, simulateMouseClick } from '../../../ClientUtils';
@@ -41,14 +38,15 @@ import { CollectionView } from './CollectionView';
import { TreeSort } from './TreeSort';
import './TreeView.scss';
+// eslint-disable-next-line @typescript-eslint/no-var-requires
const { TREE_BULLET_WIDTH } = require('../global/globalCssVariables.module.scss'); // prettier-ignore
export interface TreeViewProps {
treeView: CollectionTreeView;
// eslint-disable-next-line no-use-before-define
parentTreeView: TreeView | CollectionTreeView | undefined;
- observeHeight: (ref: any) => void;
- unobserveHeight: (ref: any) => void;
+ observeHeight: (ref: HTMLDivElement) => void;
+ unobserveHeight: (ref: HTMLDivElement) => void;
prevSibling?: Doc;
Document: Doc;
dataDoc?: Doc;
@@ -188,7 +186,7 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> {
moving: boolean = false;
@undoBatch move = (doc: Doc | Doc[], target: Doc | undefined, addDoc: (doc: Doc | Doc[]) => boolean) => {
if (this.Document !== target && addDoc !== returnFalse) {
- const canAdd1 = (this._props.parentTreeView as any).dropping || !(ComputedField.WithoutComputed(() => FieldValue(this._props.parentTreeView?.Document.data)) instanceof ComputedField);
+ const canAdd1 = (this._props.parentTreeView as TreeView).dropping || !(ComputedField.WithoutComputed(() => FieldValue(this._props.parentTreeView?.Document.data)) instanceof ComputedField);
// bcz: this should all be running in a Temp undo batch instead of hackily testing for returnFalse
if (canAdd1 && this._props.removeDoc?.(doc) === true) {
@@ -263,7 +261,7 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> {
return runningChildren;
};
- static GetRunningChildren = new Map<Doc, any>();
+ static GetRunningChildren = new Map<Doc, () => FieldResult[]>();
static ToggleChildrenRun = new Map<Doc, () => void>();
constructor(props: TreeViewProps) {
super(props);
@@ -285,7 +283,7 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> {
TreeView.GetRunningChildren.set(this.Document, () => this.getRunningChildren(this.childDocs));
}
- _treeEle: any;
+ _treeEle: HTMLDivElement | null = null;
protected createTreeDropTarget = (ele: HTMLDivElement) => {
this._treedropDisposer?.();
ele && ((this._treedropDisposer = DragManager.MakeDropTarget(ele, this.treeDrop.bind(this), this.Document, this.preTreeDrop.bind(this))), this.Document);
@@ -524,7 +522,7 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> {
return toList(docs).reduce((flg, iDoc) => flg && innerAdd(iDoc), true as boolean);
};
contentElement = TreeView.GetChildElements(
- toList(contents as any),
+ contents instanceof Doc ? [contents] : DocListCast(contents),
this.treeView,
this,
doc,
@@ -572,9 +570,11 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> {
rows.push(
<div style={{ display: 'flex', overflow: 'auto' }} key={key}>
<span
- ref={action((r: any) => {
- if (r) leftOffset.width = r.getBoundingClientRect().width;
- })}
+ ref={r =>
+ runInAction(() => {
+ if (r) leftOffset.width = r.getBoundingClientRect().width;
+ })
+ }
style={{ fontWeight: 'bold' }}>
{key + ':'}
&nbsp;
@@ -608,7 +608,7 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> {
return rows;
}
- _renderTimer: any;
+ _renderTimer: NodeJS.Timeout | undefined;
@observable _renderCount = 1;
@computed get renderContent() {
TraceMobx();
@@ -754,7 +754,7 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> {
}
get onCheckedClick() {
- return this.Document.type === DocumentType.COL ? undefined : this._props.onCheckedClick?.() ?? ScriptCast(this.Document.onCheckedClick);
+ return this.Document.type === DocumentType.COL ? undefined : (this._props.onCheckedClick?.() ?? ScriptCast(this.Document.onCheckedClick));
}
@action
@@ -779,7 +779,7 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> {
TraceMobx();
const iconType = (this.treeView._props.styleProvider?.(this.Document, this.treeView._props, StyleProp.TreeViewIcon + (this.treeViewOpen ? ':treeOpen' : !this.childDocs.length ? ':empty' : '')) as string) || 'question';
const color = SettingsManager.userColor;
- const checked = this.onCheckedClick ? this.Document.treeView_Checked ?? 'unchecked' : undefined;
+ const checked = this.onCheckedClick ? (this.Document.treeView_Checked ?? 'unchecked') : undefined;
return (
<div
className={`bullet${this.treeView.outlineMode ? '-outline' : ''}`}
@@ -789,7 +789,7 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> {
style={
this.treeView.outlineMode
? {
- opacity: this.titleStyleProvider?.(this.Document, this.treeView._props, StyleProp.Opacity),
+ opacity: this.titleStyleProvider?.(this.Document, this.treeView._props, StyleProp.Opacity) as number,
}
: {
pointerEvents: this._props.isContentActive() ? 'all' : undefined,
@@ -829,7 +829,7 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> {
@action
expandNextviewType = () => {
if (this.treeViewOpen && !this.Document.isFolder && !this.treeView.outlineMode && !this.Document.treeView_ExpandedViewLock) {
- const next = (modes: any[]) => modes[(modes.indexOf(StrCast(this.treeViewExpandedView)) + 1) % modes.length];
+ const next = (modes: string[]) => modes[(modes.indexOf(StrCast(this.treeViewExpandedView)) + 1) % modes.length];
this.Document.treeView_ExpandedView = next(this.validExpandViewTypes);
}
this.treeViewOpen = true;
@@ -897,13 +897,13 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> {
onChildDoubleClick = () => ScriptCast(this.treeView.Document.treeView_ChildDoubleClick, !this.treeView.outlineMode ? this._openScript?.() : null);
refocus = () => this.treeView._props.focus(this.treeView.Document, {});
- ignoreEvent = (e: any) => {
+ ignoreEvent = (e: React.MouseEvent) => {
if (this._props.isContentActive(true)) {
e.stopPropagation();
e.preventDefault();
}
};
- titleStyleProvider = (doc: Doc | undefined, props: Opt<FieldViewProps>, property: string): any => {
+ titleStyleProvider = (doc: Doc | undefined, props: Opt<FieldViewProps>, property: string) => {
if (!doc || doc !== this.Document) return this._props?.treeView?._props.styleProvider?.(doc, props, property); // properties are inherited from the CollectionTreeView, not the hierarchical parent in the treeView
const { treeView } = this;
@@ -938,7 +938,7 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> {
}
return treeView._props.styleProvider?.(doc, props, property);
};
- embeddedStyleProvider = (doc: Doc | undefined, props: Opt<FieldViewProps>, property: string): any => {
+ embeddedStyleProvider = (doc: Doc | undefined, props: Opt<FieldViewProps>, property: string) => {
if (property.startsWith(StyleProp.Decorations)) return null;
return this._props?.treeView?._props.styleProvider?.(doc, props, property); // properties are inherited from the CollectionTreeView, not the hierarchical parent in the treeView
};
@@ -990,28 +990,30 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> {
this._editTitle = e;
})}
GetValue={() => StrCast(this.Document.title)}
- OnTab={undoBatch((shift?: boolean) => {
+ OnTab={undoable((shift?: boolean) => {
if (!shift) this._props.indentDocument?.(true);
else this._props.outdentDocument?.(true);
- })}
- OnEmpty={undoBatch(() => this.treeView.outlineMode && this._props.removeDoc?.(this.Document))}
+ }, 'create new tree Doc')}
+ OnEmpty={undoable(() => this.treeView.outlineMode && this._props.removeDoc?.(this.Document), 'remove tree doc')}
OnFillDown={() => this.treeView.fileSysMode && this.makeFolder()}
- SetValue={undoBatch((value: string, shiftKey: boolean, enterKey: boolean) => {
+ SetValue={undoable((value: string, shiftKey: boolean, enterKey: boolean) => {
Doc.SetInPlace(this.Document, 'title', value, false);
- this.treeView.outlineMode && enterKey && this.makeTextCollection();
- })}
+ return this.treeView.outlineMode && enterKey && this.makeTextCollection();
+ }, 'set tree doc title')}
/>
) : (
<DocumentView
key="title"
- ref={action((r: any) => {
- this._docRef = r || undefined;
- if (this._docRef && TreeView._editTitleOnLoad?.id === this.Document[Id] && TreeView._editTitleOnLoad.parent === this._props.parentTreeView) {
- this._docRef.select(false);
- this.setEditTitle(this._docRef);
- TreeView._editTitleOnLoad = undefined;
- }
- })}
+ ref={r =>
+ runInAction(() => {
+ this._docRef = r || undefined;
+ if (this._docRef && TreeView._editTitleOnLoad?.id === this.Document[Id] && TreeView._editTitleOnLoad.parent === this._props.parentTreeView) {
+ this._docRef.select(false);
+ this.setEditTitle(this._docRef);
+ TreeView._editTitleOnLoad = undefined;
+ }
+ })
+ }
Document={this.Document}
fitWidth={returnTrue}
scriptContext={this}
@@ -1068,9 +1070,11 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> {
</div>
<div
className="treeView-rightButtons"
- ref={action((r: any) => {
- r && (this.headerEleWidth = r.getBoundingClientRect().width);
- })}>
+ ref={r =>
+ runInAction(() => {
+ r && (this.headerEleWidth = r.getBoundingClientRect().width);
+ })
+ }>
{this.titleButtons}
</div>
</>
@@ -1090,7 +1094,7 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> {
this,
e,
() => {
- (this._dref ?? this._docRef)?.startDragging(e.clientX, e.clientY, '' as any);
+ (this._dref ?? this._docRef)?.startDragging(e.clientX, e.clientY, undefined);
return true;
},
returnFalse,
@@ -1272,8 +1276,8 @@ export class TreeView extends ObservableReactComponent<TreeViewProps> {
firstLevel: boolean,
whenChildContentsActiveChanged: (isActive: boolean) => void,
dontRegisterView: boolean | undefined,
- observerHeight: (ref: any) => void,
- unobserveHeight: (ref: any) => void,
+ observerHeight: (ref: HTMLElement) => void,
+ unobserveHeight: (ref: HTMLElement) => void,
contextMenuItems: { script: ScriptField; filter: ScriptField; label: string; icon: string }[],
// TODO: [AL] add these
AddToMap?: (treeViewDoc: Doc, index: number[]) => void,
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoState.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoState.tsx
index fc39cafaa..c17371151 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoState.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormInfoState.tsx
@@ -12,7 +12,7 @@ import './CollectionFreeFormView.scss';
* returns a truthy value
*/
// eslint-disable-next-line no-use-before-define
-export type infoArc = [() => any, (res?: any) => infoState];
+export type infoArc = [() => unknown, (res?: unknown) => infoState];
export const StateMessage = Symbol('StateMessage');
export const StateMessageGIF = Symbol('StateMessageGIF');
@@ -20,9 +20,9 @@ export const StateEntryFunc = Symbol('StateEntryFunc');
export class infoState {
[StateMessage]: string = '';
[StateMessageGIF]?: string = '';
- [StateEntryFunc]?: () => any;
+ [StateEntryFunc]?: () => unknown;
[key: string]: infoArc;
- constructor(message: string, arcs: { [key: string]: infoArc }, messageGif?: string, entryFunc?: () => any) {
+ constructor(message: string, arcs: { [key: string]: infoArc }, messageGif?: string, entryFunc?: () => unknown) {
this[StateMessage] = message;
Object.assign(this, arcs);
this[StateMessageGIF] = messageGif;
@@ -44,7 +44,7 @@ export function InfoState(
msg: string, //
arcs: { [key: string]: infoArc },
gif?: string,
- entryFunc?: () => any
+ entryFunc?: () => unknown
) {
// eslint-disable-next-line new-cap
return new infoState(msg, arcs, gif, entryFunc);
@@ -52,7 +52,7 @@ export function InfoState(
export interface CollectionFreeFormInfoStateProps {
infoState: infoState;
- next: (state: infoState) => any;
+ next: (state: infoState) => unknown;
close: () => void;
}
@@ -61,7 +61,7 @@ export class CollectionFreeFormInfoState extends ObservableReactComponent<Collec
_disposers: IReactionDisposer[] = [];
@observable _expanded = false;
- constructor(props: any) {
+ constructor(props: CollectionFreeFormInfoStateProps) {
super(props);
makeObservable(this);
}
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormPannableContents.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormPannableContents.tsx
index e543b4008..bc9dd022c 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormPannableContents.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormPannableContents.tsx
@@ -54,8 +54,8 @@ export class CollectionFreeFormPannableContents extends ObservableReactComponent
<div
className={'collectionfreeformview' + (this._props.viewDefDivClick ? '-viewDef' : '-none')}
onScroll={e => {
- const target = e.target as any;
- if (getComputedStyle(target)?.overflow === 'visible') {
+ const { target } = e;
+ if (target instanceof Element && getComputedStyle(target)?.overflow === 'visible') {
target.scrollTop = target.scrollLeft = 0; // if collection is visible, scrolling messes things up since there are no scroll bars
}
}}
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 39c3da7a5..c4cf8dee7 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -1,6 +1,7 @@
/* eslint-disable react/jsx-props-no-spreading */
import { Bezier } from 'bezier-js';
import { Colors } from 'browndash-components';
+import { Property } from 'csstype';
import { action, computed, IReactionDisposer, makeObservable, observable, reaction, runInAction } from 'mobx';
import { observer } from 'mobx-react';
import { computedFn } from 'mobx-utils';
@@ -8,7 +9,6 @@ import * as React from 'react';
import { ClientUtils, DashColor, lightOrDark, OmitKeys, returnFalse, returnZero, setupMoveUpEvents, UpdateIcon } from '../../../../ClientUtils';
import { DateField } from '../../../../fields/DateField';
import { Doc, DocListCast, Field, FieldType, Opt, StrListCast } from '../../../../fields/Doc';
-import { ActiveArrowEnd, ActiveArrowStart, ActiveDash, ActiveEraserWidth, ActiveInkBezierApprox, ActiveInkColor, ActiveInkWidth, ActiveIsInkMask, SetActiveInkColor, SetActiveInkWidth } from '../../nodes/DocumentView';
import { DocData, Height, Width } from '../../../../fields/DocSymbols';
import { Id } from '../../../../fields/FieldSymbols';
import { InkData, InkField, InkTool, Segment } from '../../../../fields/InkField';
@@ -31,13 +31,13 @@ import { CompileScript } from '../../../util/Scripting';
import { ScriptingGlobals } from '../../../util/ScriptingGlobals';
import { freeformScrollMode, SnappingManager } from '../../../util/SnappingManager';
import { Transform } from '../../../util/Transform';
-import { undoable, undoBatch, UndoManager } from '../../../util/UndoManager';
+import { undoable, UndoManager } from '../../../util/UndoManager';
import { Timeline } from '../../animationtimeline/Timeline';
import { ContextMenu } from '../../ContextMenu';
import { InkingStroke } from '../../InkingStroke';
import { CollectionFreeFormDocumentView } from '../../nodes/CollectionFreeFormDocumentView';
import { SchemaCSVPopUp } from '../../nodes/DataVizBox/SchemaCSVPopUp';
-import { ActiveFillColor, DocumentView } from '../../nodes/DocumentView';
+import { ActiveArrowEnd, ActiveArrowStart, ActiveDash, ActiveEraserWidth, ActiveFillColor, ActiveInkBezierApprox, ActiveInkColor, ActiveInkWidth, ActiveIsInkMask, DocumentView, SetActiveInkColor, SetActiveInkWidth } from '../../nodes/DocumentView';
import { FieldViewProps } from '../../nodes/FieldView';
import { FocusViewOptions } from '../../nodes/FocusViewOptions';
import { FormattedTextBox } from '../../nodes/formattedText/FormattedTextBox';
@@ -121,7 +121,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
@observable _marqueeViewRef = React.createRef<MarqueeView>();
@observable _brushedView: { width: number; height: number; panX: number; panY: number } | undefined = undefined; // highlighted region of freeform canvas used by presentations to indicate a region
@observable GroupChildDrag: boolean = false; // child document view being dragged. needed to update drop areas of groups when a group item is dragged.
- @observable _childPointerEvents: 'none' | 'all' | 'visiblePainted' | undefined = undefined;
+ @observable _childPointerEvents: Property.PointerEvents | undefined = undefined;
@observable _lightboxDoc: Opt<Doc> = undefined;
@observable _paintedId = 'id' + Utils.GenerateGuid().replace(/-/g, '');
@observable _keyframeEditing = false;
@@ -441,8 +441,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
return true;
}
- @undoBatch
- internalAnchorAnnoDrop(e: Event, de: DragManager.DropEvent, annoDragData: DragManager.AnchorAnnoDragData) {
+ internalAnchorAnnoDrop = undoable((e: Event, de: DragManager.DropEvent, annoDragData: DragManager.AnchorAnnoDragData) => {
const dropCreator = annoDragData.dropDocCreator;
const [xp, yp] = this.screenToFreeformContentsXf.transformPoint(de.x, de.y);
annoDragData.dropDocCreator = (annotationOn: Doc | undefined) => {
@@ -455,10 +454,9 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
return dropDoc || this.Document;
};
return true;
- }
+ }, 'anchor drop');
- @undoBatch
- internalLinkDrop(e: Event, de: DragManager.DropEvent, linkDragData: DragManager.LinkDragData) {
+ internalLinkDrop = undoable((e: Event, de: DragManager.DropEvent, linkDragData: DragManager.LinkDragData) => {
if (this.DocumentView?.() && linkDragData.linkDragView.containerViewPath?.().includes(this.DocumentView())) {
const [x, y] = this.screenToFreeformContentsXf.transformPoint(de.x, de.y);
// do nothing if link is dropped into any freeform view parent of dragged document
@@ -474,9 +472,9 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
return added;
}
return false;
- }
+ }, 'link drop');
- onInternalDrop = (e: Event, de: DragManager.DropEvent) => {
+ onInternalDrop = (e: Event, de: DragManager.DropEvent): boolean => {
if (de.complete.annoDragData?.dragDocument && super.onInternalDrop(e, de)) return this.internalAnchorAnnoDrop(e, de, de.complete.annoDragData);
if (de.complete.linkDragData) return this.internalLinkDrop(e, de, de.complete.linkDragData);
if (de.complete.docDragData?.droppedDocuments.length) return this.internalDocDrop(e, de, de.complete.docDragData);
@@ -522,8 +520,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
}
};
- @undoBatch
- onGesture = (e: Event, ge: GestureUtils.GestureEvent) => {
+ onGesture = undoable((e: Event, ge: GestureUtils.GestureEvent) => {
switch (ge.gesture) {
case Gestures.Text:
if (ge.text) {
@@ -566,7 +563,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
e.stopPropagation();
}
}
- };
+ }, 'gesture');
@action
onEraserUp = (): void => {
this._deleteList.lastElement()?._props.removeDocument?.(this._deleteList.map(ink => ink.Document));
@@ -1484,8 +1481,8 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
const childData = entry.pair.data;
return (
<CollectionFreeFormDocumentView
- // eslint-disable-next-line react/jsx-props-no-spreading
- {...OmitKeys(entry, ['replica', 'pair']).omit}
+ // eslint-disable-next-line react/jsx-props-no-spreading, @typescript-eslint/no-explicit-any
+ {...(OmitKeys(entry, ['replica', 'pair']).omit as any)}
key={childLayout[Id] + (entry.replica || '')}
Document={childLayout}
reactParent={this}
@@ -1771,7 +1768,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
this._disposers.pointerevents = reaction(
() => this.childPointerEvents,
pointerevents => {
- this._childPointerEvents = pointerevents as 'none' | 'all' | 'visiblePainted' | undefined;
+ this._childPointerEvents = pointerevents as Property.PointerEvents | undefined;
},
{ fireImmediately: true }
);
@@ -1849,8 +1846,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
this._showEraserCircle = true;
};
- @undoBatch
- promoteCollection = () => {
+ promoteCollection = undoable(() => {
const childDocs = this.childDocs.slice();
childDocs.forEach(docIn => {
const doc = docIn;
@@ -1859,10 +1855,9 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
doc.y = scr?.[1];
});
this._props.addDocTab(childDocs, OpenWhere.inParentFromScreen);
- };
+ }, 'promote collection');
- @undoBatch
- layoutDocsInGrid = () => {
+ layoutDocsInGrid = undoable(() => {
const docs = this.childLayoutPairs.map(pair => pair.layout);
const width = Math.max(...docs.map(doc => NumCast(doc._width))) + 20;
const height = Math.max(...docs.map(doc => NumCast(doc._height))) + 20;
@@ -1872,40 +1867,37 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
doc.x = NumCast(this.Document[this.panXFieldKey]) + (i % dim) * width - (width * dim) / 2;
doc.y = NumCast(this.Document[this.panYFieldKey]) + Math.floor(i / dim) * height - (height * dim) / 2;
});
- };
+ }, 'layout docs in grid');
- @undoBatch
- toggleNativeDimensions = () => Doc.toggleNativeDimensions(this.layoutDoc, 1, this.nativeWidth, this.nativeHeight);
+ toggleNativeDimensions = undoable(() => Doc.toggleNativeDimensions(this.layoutDoc, 1, this.nativeWidth, this.nativeHeight), 'toggle native dimensions');
///
/// resetView restores a freeform collection to unit scale and centered at (0,0) UNLESS
/// the view is a group, in which case this does nothing (since Groups calculate their own scale and center)
///
- @undoBatch
- resetView = () => {
+ resetView = undoable(() => {
this.layoutDoc[this.panXFieldKey] = NumCast(this.dataDoc[this.panXFieldKey + '_reset']);
this.layoutDoc[this.panYFieldKey] = NumCast(this.dataDoc[this.panYFieldKey + '_reset']);
this.layoutDoc[this.scaleFieldKey] = NumCast(this.dataDoc[this.scaleFieldKey + '_reset'], 1);
- };
+ }, 'reset view');
///
/// resetView restores a freeform collection to unit scale and centered at (0,0) UNLESS
/// the view is a group, in which case this does nothing (since Groups calculate their own scale and center)
///
- @undoBatch
- toggleResetView = () => {
+ toggleResetView = undoable(() => {
this.dataDoc[this.autoResetFieldKey] = !this.dataDoc[this.autoResetFieldKey];
if (this.dataDoc[this.autoResetFieldKey]) {
this.dataDoc[this.panXFieldKey + '_reset'] = this.layoutDoc[this.panXFieldKey];
this.dataDoc[this.panYFieldKey + '_reset'] = this.layoutDoc[this.panYFieldKey];
this.dataDoc[this.scaleFieldKey + '_reset'] = this.layoutDoc[this.scaleFieldKey];
}
- };
+ }, 'toggle reset view');
onContextMenu = () => {
if (this._props.isAnnotationOverlay || !ContextMenu.Instance) return;
const appearance = ContextMenu.Instance.findByDescription('Appearance...');
- const appearanceItems = appearance && 'subitems' in appearance ? appearance.subitems : [];
+ const appearanceItems = appearance?.subitems ?? [];
!this.Document.isGroup && appearanceItems.push({ description: 'Reset View', event: this.resetView, icon: 'compress-arrows-alt' });
!this.Document.isGroup && appearanceItems.push({ description: 'Toggle Auto Reset View', event: this.toggleResetView, icon: 'compress-arrows-alt' });
if (this._props.setContentViewBox === emptyFunction) {
@@ -1932,7 +1924,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
!appearance && ContextMenu.Instance.addItem({ description: 'Appearance...', subitems: appearanceItems, icon: 'eye' });
const options = ContextMenu.Instance.findByDescription('Options...');
- const optionItems = options && 'subitems' in options ? options.subitems : [];
+ const optionItems = options?.subitems ?? [];
!this._props.isAnnotationOverlay &&
!Doc.noviceMode &&
optionItems.push({
@@ -1956,12 +1948,11 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
}
!options && ContextMenu.Instance.addItem({ description: 'Options...', subitems: optionItems, icon: 'eye' });
const mores = ContextMenu.Instance.findByDescription('More...');
- const moreItems = mores && 'subitems' in mores ? mores.subitems : [];
+ const moreItems = mores?.subitems ?? [];
!mores && ContextMenu.Instance.addItem({ description: 'More...', subitems: moreItems, icon: 'eye' });
};
- @undoBatch
- transcribeStrokes = () => {
+ transcribeStrokes = undoable(() => {
if (this.Document.isGroup && this.Document.transcription) {
const text = StrCast(this.Document.transcription);
const lines = text.split('\n');
@@ -1969,7 +1960,7 @@ export class CollectionFreeFormView extends CollectionSubView<Partial<collection
this.addDocument(Docs.Create.TextDocument(text, { title: lines[0], x: NumCast(this.layoutDoc.x) + NumCast(this.layoutDoc._width) + 20, y: NumCast(this.layoutDoc.y), _width: 200, _height: height }));
}
- };
+ }, 'transcribe strokes');
@action
dragEnding = () => {
diff --git a/src/client/views/collections/collectionLinear/CollectionLinearView.tsx b/src/client/views/collections/collectionLinear/CollectionLinearView.tsx
index eac0dc0e1..3af8464c2 100644
--- a/src/client/views/collections/collectionLinear/CollectionLinearView.tsx
+++ b/src/client/views/collections/collectionLinear/CollectionLinearView.tsx
@@ -1,8 +1,7 @@
-/* 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 { Toggle, ToggleType, Type } from 'browndash-components';
+import { Property } from 'csstype';
import { IReactionDisposer, action, makeObservable, reaction } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
@@ -22,8 +21,7 @@ import { UndoStack } from '../../UndoStack';
import { DocumentLinksButton } from '../../nodes/DocumentLinksButton';
import { DocumentView } from '../../nodes/DocumentView';
import { LinkDescriptionPopup } from '../../nodes/LinkDescriptionPopup';
-import { CollectionSubView } from '../CollectionSubView';
-import './CollectionLinearView.scss';
+import { CollectionSubView, SubCollectionViewProps } from '../CollectionSubView';
/**
* CollectionLinearView is the class for rendering the horizontal collection
@@ -39,7 +37,7 @@ export class CollectionLinearView extends CollectionSubView() {
private _widthDisposer?: IReactionDisposer;
private _selectedDisposer?: IReactionDisposer;
- constructor(props: any) {
+ constructor(props: SubCollectionViewProps) {
super(props);
makeObservable(this);
}
@@ -239,7 +237,7 @@ export class CollectionLinearView extends CollectionSubView() {
className="collectionLinearView-content"
style={{
height: this.dimension(),
- flexDirection: flexDir as any,
+ flexDirection: flexDir as Property.FlexDirection,
gap: flexGap,
}}>
{this.childLayoutPairs.map(pair => this.getDisplayDoc(pair.layout))}
diff --git a/src/client/views/nodes/AudioBox.tsx b/src/client/views/nodes/AudioBox.tsx
index 9deed4de4..59349da8b 100644
--- a/src/client/views/nodes/AudioBox.tsx
+++ b/src/client/views/nodes/AudioBox.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, IReactionDisposer, makeObservable, observable, runInAction } from 'mobx';
@@ -7,7 +5,7 @@ import { observer } from 'mobx-react';
import * as React from 'react';
import { returnFalse, setupMoveUpEvents } from '../../../ClientUtils';
import { DateField } from '../../../fields/DateField';
-import { Doc } from '../../../fields/Doc';
+import { Doc, Opt } from '../../../fields/Doc';
import { DocData } from '../../../fields/DocSymbols';
import { ComputedField } from '../../../fields/ScriptField';
import { Cast, DateCast, NumCast } from '../../../fields/Types';
@@ -44,9 +42,9 @@ import { OpenWhere } from './OpenWhere';
*/
// used as a wrapper class for MediaStream from MediaDevices API
-declare class MediaRecorder {
- constructor(e: any); // whatever MediaRecorder has
-}
+// declare class MediaRecorder {
+// constructor(e: unknown); // whatever MediaRecorder has
+// }
export enum mediaState {
PendingRecording = 'pendingRecording',
@@ -61,9 +59,7 @@ export class AudioBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
return FieldView.LayoutString(AudioBox, fieldKey);
}
- public static Enabled = false;
-
- constructor(props: any) {
+ constructor(props: FieldViewProps) {
super(props);
makeObservable(this);
}
@@ -74,12 +70,12 @@ export class AudioBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
_dropDisposer?: DragManager.DragDropDisposer;
_disposers: { [name: string]: IReactionDisposer } = {};
_ele: HTMLAudioElement | null = null; // <audio> ref
- _recorder: any; // MediaRecorder
+ _recorder: Opt<MediaRecorder>; // MediaRecorder
_recordStart = 0;
_pauseStart = 0; // time when recording is paused (used to keep track of recording timecodes)
_pausedTime = 0;
_stream: MediaStream | undefined; // passed to MediaRecorder, records device input audio
- _play: any = null; // timeout for playback
+ _play: NodeJS.Timeout | null = null; // timeout for playback
@observable _stackedTimeline: CollectionStackedTimeline | null | undefined = undefined; // CollectionStackedTimeline ref
@observable _finished: boolean = false; // has playback reached end of clip
@@ -133,7 +129,7 @@ export class AudioBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
this.mediaState = mediaState.Paused;
this.setPlayheadTime(NumCast(this.layoutDoc.clipStart));
} else {
- this.mediaState = undefined as any as mediaState;
+ this.mediaState = undefined as unknown as mediaState;
}
}
@@ -185,11 +181,11 @@ export class AudioBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
// play back the audio from seekTimeInSeconds, fullPlay tells whether clip is being played to end vs link range
@action
playFrom = (seekTimeInSeconds: number, endTime?: number, fullPlay: boolean = false) => {
- clearTimeout(this._play); // abort any previous clip ending
+ this._play && clearTimeout(this._play); // abort any previous clip ending
if (isNaN(this._ele?.duration ?? Number.NaN)) {
// audio element isn't loaded yet... wait 1/2 second and try again
setTimeout(() => this.playFrom(seekTimeInSeconds, endTime), 500);
- } else if (this.timeline && this._ele && AudioBox.Enabled) {
+ } else if (this.timeline && this._ele) {
// trimBounds override requested playback bounds
const end = Math.min(this.timeline.trimEnd, endTime ?? this.timeline.trimEnd);
const start = Math.max(this.timeline.trimStart, seekTimeInSeconds);
@@ -253,8 +249,12 @@ export class AudioBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
this._recorder = new MediaRecorder(this._stream);
this.dataDoc[this.fieldKey + '_recordingStart'] = new DateField();
DocViewUtils.ActiveRecordings.push(this);
- this._recorder.ondataavailable = async (e: any) => {
- const [{ result }] = await Networking.UploadFilesToServer({ file: e.data });
+ this._recorder.ondataavailable = async (e: BlobEvent) => {
+ const file: Blob & { name?: string; lastModified?: number; webkitRelativePath?: string } = e.data;
+ file.name = '';
+ file.lastModified = 0;
+ file.webkitRelativePath = '';
+ const [{ result }] = await Networking.UploadFilesToServer({ file: file as Blob & { name: string; lastModified: number; webkitRelativePath: string } });
if (!(result instanceof Error)) {
this.Document[this.fieldKey] = new AudioField(result.accessPaths.agnostic.client);
}
@@ -331,9 +331,7 @@ export class AudioBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
};
// for play button
- Play = (e?: any) => {
- e?.stopPropagation?.();
-
+ Play = () => {
if (this.timeline && this._ele) {
const eleTime = this._ele.currentTime;
@@ -363,7 +361,7 @@ export class AudioBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
this.mediaState = mediaState.Paused;
// if paused in the middle of playback, prevents restart on next play
- if (!this._finished) clearTimeout(this._play);
+ if (!this._finished && this._play) clearTimeout(this._play);
}
};
// pause playback and remove from playback list
@@ -374,7 +372,7 @@ export class AudioBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
};
// for dictation button, creates a text document for dictation
- onFile = (e: any) => {
+ onFile = (e: React.PointerEvent) => {
setupMoveUpEvents(
this,
e,
@@ -419,7 +417,7 @@ export class AudioBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
action(() => {
this._pauseStart = new Date().getTime();
this._paused = true;
- this._recorder.pause();
+ this._recorder?.pause();
}),
false
);
@@ -435,7 +433,7 @@ export class AudioBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
action(() => {
this._paused = false;
this._pausedTime += new Date().getTime() - this._pauseStart;
- this._recorder.resume();
+ this._recorder?.resume();
}),
false
);
@@ -620,14 +618,10 @@ export class AudioBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
<div
className="audiobox-button"
title={this.mediaState === mediaState.Paused ? 'play' : 'pause'}
- onPointerDown={
- this.mediaState === mediaState.Paused
- ? this.Play
- : e => {
- e.stopPropagation();
- this.Pause();
- }
- }>
+ onPointerDown={e => {
+ e.stopPropagation();
+ this.mediaState === mediaState.Paused ? this.Play() : this.Pause();
+ }}>
<FontAwesomeIcon icon={this.mediaState === mediaState.Paused ? 'play' : 'pause'} size="1x" />
</div>
@@ -743,7 +737,6 @@ export class AudioBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
// returns the html audio element
@computed get audio() {
return (
- // eslint-disable-next-line jsx-a11y/media-has-caption
<audio
ref={this.setRef}
className={`audiobox-control${this._props.isContentActive() ? '-interactive' : ''}`}
diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
index 9a383c1e4..d51b1cd3a 100644
--- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
+++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
@@ -119,7 +119,7 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
super.componentDidUpdate(prevProps);
this.WrapperKeys.forEach(
action(keys => {
- (this as any)[keys.upper] = (this.props as any)[keys.lower];
+ (this as unknown as { [key: string]: unknown })[keys.upper] = (this.props as { [key: string]: unknown })[keys.lower];
})
);
}
@@ -148,7 +148,7 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
(p, val) => {
p[val.key] = Cast(doc[`${val.key}_indexed`], listSpec('number'), fillIn ? [NumCast(doc[val.key], val.val)] : []).reduce(
(prev, v, i) => ((i <= Math.round(time) && v !== undefined) || prev === undefined ? v : prev),
- undefined as any as number
+ undefined as unknown as number
);
return p;
},
@@ -159,7 +159,7 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
public static getStringValues(doc: Doc, time: number) {
return CollectionFreeFormDocumentView.animStringFields.reduce(
(p, val) => {
- p[val] = Cast(doc[`${val}_indexed`], listSpec('string'), [StrCast(doc[val])]).reduce((prev, v, i) => ((i <= Math.round(time) && v !== undefined) || prev === undefined ? v : prev), undefined as any as string);
+ p[val] = Cast(doc[`${val}_indexed`], listSpec('string'), [StrCast(doc[val])]).reduce((prev, v, i) => ((i <= Math.round(time) && v !== undefined) || prev === undefined ? v : prev), undefined as unknown as string);
return p;
},
{} as { [val: string]: Opt<string> }
@@ -202,15 +202,15 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
docs.forEach(doc => {
this.animFields.forEach(val => {
const findexed = Cast(doc[`${val.key}_indexed`], listSpec('number'), null);
- findexed?.length <= timecode + 1 && findexed.push(undefined as any as number);
+ findexed?.length <= timecode + 1 && findexed.push(undefined as unknown as number);
});
this.animStringFields.forEach(val => {
const findexed = Cast(doc[`${val}_indexed`], listSpec('string'), null);
- findexed?.length <= timecode + 1 && findexed.push(undefined as any as string);
+ findexed?.length <= timecode + 1 && findexed.push(undefined as unknown as string);
});
this.animDataFields(doc).forEach(val => {
const findexed = Cast(doc[`${val}_indexed`], listSpec(InkField), null);
- findexed?.length <= timecode + 1 && findexed.push(undefined as any);
+ findexed?.length <= timecode + 1 && findexed.push(undefined as unknown as InkField);
});
});
return newTimer;
@@ -286,7 +286,6 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
localRotation = () => this._props.rotation;
render() {
TraceMobx();
-
return (
<div
className={CollectionFreeFormDocumentView.CollectionFreeFormDocViewClassName}
@@ -304,10 +303,19 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
<DocumentView
// eslint-disable-next-line react/jsx-props-no-spreading
{...OmitKeys(this._props,this.WrapperKeys.map(val => val.lower)).omit} // prettier-ignore
+ Document={this._props.Document}
+ renderDepth={this._props.renderDepth}
+ isContentActive={this._props.isContentActive}
+ childFilters={this._props.childFilters}
+ childFiltersByRanges={this._props.childFilters}
+ pinToPres={this._props.pinToPres}
+ addDocTab={this._props.addDocTab}
+ searchFilterDocs={this._props.searchFilterDocs}
+ focus={this._props.focus}
+ whenChildContentsActiveChanged={this._props.whenChildContentsActiveChanged}
reactParent={this}
DataTransition={this.DataTransition}
LocalRotation={this.localRotation}
- CollectionFreeFormDocumentView={this.returnThis}
styleProvider={this.styleProvider}
ScreenToLocalTransform={this.screenToLocalTransform}
isGroupActive={this.isGroupActive}
diff --git a/src/client/views/nodes/ComparisonBox.tsx b/src/client/views/nodes/ComparisonBox.tsx
index efaf6807a..1eae163df 100644
--- a/src/client/views/nodes/ComparisonBox.tsx
+++ b/src/client/views/nodes/ComparisonBox.tsx
@@ -162,14 +162,14 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
() => this.clearDoc(which)
);
};
- docStyleProvider = (doc: Opt<Doc>, props: Opt<FieldViewProps>, property: string): any => {
+ docStyleProvider = (doc: Opt<Doc>, props: Opt<FieldViewProps>, property: string) => {
switch (property) {
case StyleProp.PointerEvents: return 'none';
default: return this._props.styleProvider?.(doc, props, property);
} // prettier-ignore
};
- moveDoc1 = (docs: Doc | Doc[], targetCol: Doc | undefined, addDoc: any) => toList(docs).reduce((res, doc: Doc) => res && this.moveDoc(doc, addDoc, this.fieldKey + '_1'), true);
- moveDoc2 = (docs: Doc | Doc[], targetCol: Doc | undefined, addDoc: any) => toList(docs).reduce((res, doc: Doc) => res && this.moveDoc(doc, addDoc, this.fieldKey + '_2'), true);
+ moveDoc1 = (docs: Doc | Doc[], targetCol: Doc | undefined, addDoc: (doc: Doc | Doc[]) => boolean) => toList(docs).reduce((res, doc: Doc) => res && this.moveDoc(doc, addDoc, this.fieldKey + '_1'), true);
+ moveDoc2 = (docs: Doc | Doc[], targetCol: Doc | undefined, addDoc: (doc: Doc | Doc[]) => boolean) => toList(docs).reduce((res, doc: Doc) => res && this.moveDoc(doc, addDoc, this.fieldKey + '_2'), true);
remDoc1 = (docs: Doc | Doc[]) => toList(docs).reduce((res, doc) => res && this.remDoc(doc, this.fieldKey + '_1'), true);
remDoc2 = (docs: Doc | Doc[]) => toList(docs).reduce((res, doc) => res && this.remDoc(doc, this.fieldKey + '_2'), true);
@@ -420,7 +420,6 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
}
Docs.Prototypes.TemplateMap.set(DocumentType.COMPARISON, {
- data: '',
layout: { view: ComparisonBox, dataField: 'data' },
options: {
acl: '',
diff --git a/src/client/views/nodes/DataVizBox/DataVizBox.tsx b/src/client/views/nodes/DataVizBox/DataVizBox.tsx
index baf8693ca..69277b054 100644
--- a/src/client/views/nodes/DataVizBox/DataVizBox.tsx
+++ b/src/client/views/nodes/DataVizBox/DataVizBox.tsx
@@ -50,7 +50,7 @@ export class DataVizBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
sidebarAddDoc: ((doc: Doc | Doc[], sidebarKey?: string | undefined) => boolean) | undefined;
crop: ((region: Doc | undefined, addCrop?: boolean) => Doc | undefined) | undefined;
@observable _marqueeing: number[] | undefined = undefined;
- @observable _savedAnnotations = new ObservableMap<number, (HTMLDivElement & { marqueeing?: boolean})[]>();
+ @observable _savedAnnotations = new ObservableMap<number, (HTMLDivElement & { marqueeing?: boolean })[]>();
constructor(props: FieldViewProps) {
super(props);
@@ -150,7 +150,7 @@ export class DataVizBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
const visibleAnchor = AnchorMenu.Instance.GetAnchor?.(undefined, addAsAnnotation);
const anchor = !pinProps
? this.Document
- : this._vizRenderer?.getAnchor(pinProps) ??
+ : (this._vizRenderer?.getAnchor(pinProps) ??
visibleAnchor ??
Docs.Create.ConfigDocument({
title: 'ImgAnchor:' + this.Document.title,
@@ -161,7 +161,7 @@ export class DataVizBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
// when we clear selection -> we should have it so chartBox getAnchor returns undefined
// this is for when we want the whole doc (so when the chartBox getAnchor returns without a marker)
/* put in some options */
- });
+ }));
anchor.config_dataViz = this.dataVizView;
anchor.config_dataVizAxes = this.axes.length ? new List<string>(this.axes) : undefined;
anchor.dataViz_selectedRows = Field.Copy(this.layoutDoc.dataViz_selectedRows);
@@ -450,7 +450,7 @@ export class DataVizBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
* it appears to the right of this document, with the
* parameters passed in being used to create an initial display
*/
- createFilteredDoc = (axes?: any) => {
+ createFilteredDoc = (axes?: string[]) => {
const embedding = Doc.MakeEmbedding(this.Document!);
embedding._layout_showSidebar = false;
embedding._dataViz = DataVizView.LINECHART;
diff --git a/src/client/views/nodes/DataVizBox/SchemaCSVPopUp.tsx b/src/client/views/nodes/DataVizBox/SchemaCSVPopUp.tsx
index 60bc8df18..a6a6a6b46 100644
--- a/src/client/views/nodes/DataVizBox/SchemaCSVPopUp.tsx
+++ b/src/client/views/nodes/DataVizBox/SchemaCSVPopUp.tsx
@@ -1,5 +1,3 @@
-/* eslint-disable jsx-a11y/label-has-associated-control */
-/* eslint-disable jsx-a11y/alt-text */
import { IconButton } from 'browndash-components';
import { action, makeObservable, observable } from 'mobx';
import { observer } from 'mobx-react';
diff --git a/src/client/views/nodes/DataVizBox/components/TableBox.tsx b/src/client/views/nodes/DataVizBox/components/TableBox.tsx
index d2e82284e..7179356b2 100644
--- a/src/client/views/nodes/DataVizBox/components/TableBox.tsx
+++ b/src/client/views/nodes/DataVizBox/components/TableBox.tsx
@@ -1,5 +1,3 @@
-/* eslint-disable jsx-a11y/no-noninteractive-tabindex */
-/* eslint-disable jsx-a11y/no-static-element-interactions */
import { Button, Type } from 'browndash-components';
import { IReactionDisposer, action, computed, makeObservable, observable, reaction, runInAction } from 'mobx';
import { observer } from 'mobx-react';
@@ -24,7 +22,7 @@ const { DATA_VIZ_TABLE_ROW_HEIGHT } = require('../../../global/globalCssVariable
interface TableBoxProps {
Document: Doc;
layoutDoc: Doc;
- records: { [key: string]: any }[];
+ records: { [key: string]: unknown }[];
selectAxes: (axes: string[]) => void;
selectTitleCol: (titleCol: string) => void;
axes: string[];
@@ -48,14 +46,14 @@ export class TableBox extends ObservableReactComponent<TableBoxProps> {
@observable settingTitle: boolean = false; // true when setting a title column
@observable hasRowsToFilter: boolean = false; // true when any rows are selected
@observable filtering: boolean = false; // true when the filtering menu is open
- @observable filteringColumn: any = ''; // column to filter
+ @observable filteringColumn = ''; // column to filter
@observable filteringType: string = 'Value'; // "Value" or "Range"
- filteringVal: any[] = ['', '']; // value or range to filter the column with
+ filteringVal = ['', '']; // value or range to filter the column with
@observable _scrollTop = -1;
@observable _tableHeight = 0;
@observable _tableContainerHeight = 0;
- constructor(props: any) {
+ constructor(props: TableBoxProps) {
super(props);
makeObservable(this);
}
@@ -141,17 +139,21 @@ export class TableBox extends ObservableReactComponent<TableBoxProps> {
e,
moveEv => {
// dragging off a column to create a brushed DataVizBox
- const sourceAnchorCreator = () => this._props.docView?.()!.Document!;
+ const sourceAnchorCreator = () => this._props.docView?.()?.Document || this._props.Document;
const targetCreator = (annotationOn: Doc | undefined) => {
- const embedding = Doc.MakeEmbedding(this._props.docView?.()!.Document!);
- embedding._dataViz = DataVizView.TABLE;
- embedding._dataViz_axes = new List<string>([col]);
- embedding._dataViz_parentViz = this._props.Document;
- embedding.annotationOn = annotationOn;
- embedding.histogramBarColors = Field.Copy(this._props.layoutDoc.histogramBarColors);
- embedding.defaultHistogramColor = this._props.layoutDoc.defaultHistogramColor;
- embedding.pieSliceColors = Field.Copy(this._props.layoutDoc.pieSliceColors);
- return embedding;
+ const doc = this._props.docView?.()?.Document;
+ if (doc) {
+ const embedding = Doc.MakeEmbedding(doc);
+ embedding._dataViz = DataVizView.TABLE;
+ embedding._dataViz_axes = new List<string>([col]);
+ embedding._dataViz_parentViz = this._props.Document;
+ embedding.annotationOn = annotationOn;
+ embedding.histogramBarColors = Field.Copy(this._props.layoutDoc.histogramBarColors);
+ embedding.defaultHistogramColor = this._props.layoutDoc.defaultHistogramColor;
+ embedding.pieSliceColors = Field.Copy(this._props.layoutDoc.pieSliceColors);
+ return embedding;
+ }
+ return this._props.Document;
};
if (this._props.docView?.() && !ClientUtils.isClick(moveEv.clientX, moveEv.clientY, downX, downY, Date.now())) {
DragManager.StartAnchorAnnoDrag(moveEv.target instanceof HTMLElement ? [moveEv.target] : [], new DragManager.AnchorAnnoDragData(this._props.docView()!, sourceAnchorCreator, targetCreator), downX, downY, {
@@ -188,9 +190,9 @@ export class TableBox extends ObservableReactComponent<TableBoxProps> {
/**
* These functions handle the filtering popup for when the "filter" button is pressed to select rows
*/
- filter = undoable((e: any) => {
- let start: any;
- let end: any;
+ filter = undoable((e: React.MouseEvent) => {
+ let start: string | number;
+ let end: string | number;
if (this.filteringType === 'Range') {
start = Number.isNaN(Number(this.filteringVal[0])) ? this.filteringVal[0] : Number(this.filteringVal[0]);
end = Number.isNaN(Number(this.filteringVal[1])) ? this.filteringVal[1] : Number(this.filteringVal[1]);
@@ -204,8 +206,8 @@ export class TableBox extends ObservableReactComponent<TableBoxProps> {
}
}
} else {
- let compare = this._props.records[rowID][this.filteringColumn];
- if (compare as Number) compare = Number(compare);
+ let compare = this._props.records[rowID][this.filteringColumn] as string | number;
+ if (Number(compare) == compare) compare = Number(compare);
if (start <= compare && compare <= end) {
if (!NumListCast(this._props.layoutDoc.dataViz_selectedRows).includes(rowID)) {
this.tableRowClick(e, rowID);
@@ -218,11 +220,11 @@ export class TableBox extends ObservableReactComponent<TableBoxProps> {
this.filteringVal = ['', ''];
}, 'filter table');
@action
- setFilterColumn = (e: any) => {
+ setFilterColumn = (e: React.ChangeEvent<HTMLSelectElement>) => {
this.filteringColumn = e.currentTarget.value;
};
@action
- setFilterType = (e: any) => {
+ setFilterType = (e: React.ChangeEvent<HTMLSelectElement>) => {
this.filteringType = e.currentTarget.value;
};
changeFilterValue = action((e: React.ChangeEvent<HTMLInputElement>) => {
@@ -240,7 +242,7 @@ export class TableBox extends ObservableReactComponent<TableBoxProps> {
<div className="tableBox-filterPopup" style={{ right: this._props.width * 0.05 }}>
<div className="tableBox-filterPopup-selectColumn">
Column:
- <select className="tableBox-filterPopup-selectColumn-each" value={this.filteringColumn !== '' ? this.filteringColumn : this.columns[0]} onChange={e => this.setFilterColumn(e)}>
+ <select className="tableBox-filterPopup-selectColumn-each" value={this.filteringColumn !== '' ? this.filteringColumn : this.columns[0]} onChange={this.setFilterColumn}>
{this.columns.map(column => (
<option className="" key={column} value={column}>
{' '}
@@ -250,7 +252,7 @@ export class TableBox extends ObservableReactComponent<TableBoxProps> {
</select>
</div>
<div className="tableBox-filterPopup-setValue">
- <select className="tableBox-filterPopup-setValue-each" value={this.filteringType} onChange={e => this.setFilterType(e)}>
+ <select className="tableBox-filterPopup-setValue-each" value={this.filteringType} onChange={this.setFilterType}>
<option className="" key="Value" value="Value">
{' '}
{'Value'}{' '}
@@ -307,7 +309,7 @@ export class TableBox extends ObservableReactComponent<TableBoxProps> {
)}
</div>
<div className="tableBox-filterPopup-setFilter">
- <Button onClick={action(e => this.filter(e))} text="Set Filter" type={Type.SEC} color="black" />
+ <Button onClick={this.filter} text="Set Filter" type={Type.SEC} color="black" />
</div>
</div>
);
@@ -451,7 +453,7 @@ export class TableBox extends ObservableReactComponent<TableBoxProps> {
if (this._props.titleCol === col) colSelected = true;
return (
<td key={this.columns.indexOf(col)} style={{ border: colSelected ? '3px solid black' : '1px solid black', fontWeight: colSelected ? 'bolder' : 'normal' }}>
- <div className="tableBox-cell">{this._props.records[rowId][col]}</div>
+ <div className="tableBox-cell">{this._props.records[rowId][col] as string | number}</div>
</td>
);
})}
diff --git a/src/client/views/nodes/DocumentContentsView.tsx b/src/client/views/nodes/DocumentContentsView.tsx
index 192c7875e..8a2c4e530 100644
--- a/src/client/views/nodes/DocumentContentsView.tsx
+++ b/src/client/views/nodes/DocumentContentsView.tsx
@@ -43,26 +43,37 @@ interface HTMLtagProps {
@observer
export class HTMLtag extends React.Component<HTMLtagProps> {
click = () => {
- const clickScript = (this.props as any).onClick as Opt<ScriptField>;
+ const clickScript = this.props.onClick as Opt<ScriptField>;
clickScript?.script.run({ this: this.props.Document, scale: this.props.scaling });
};
- onInput = (e: React.FormEvent<HTMLDivElement>) => {
- const onInputScript = (this.props as any).onInput as Opt<ScriptField>;
- onInputScript?.script.run({ this: this.props.Document, value: (e.target as any).textContent });
+ onInput = (e: React.FormEvent<unknown>) => {
+ const onInputScript = this.props.onInput as Opt<ScriptField>;
+ onInputScript?.script.run({ this: this.props.Document, value: (e.target as HTMLElement).textContent });
};
render() {
- const style: { [key: string]: any } = {};
- const divKeys = OmitKeys(this.props, ['children', 'dragStarting', 'dragEnding', 'htmltag', 'scaling', 'Document', 'key', 'onInput', 'onClick', '__proto__']).omit;
- const replacer = (match: any, expr: string) =>
+ const style: { [key: string]: unknown } = {};
+ const divKeys = OmitKeys(this.props, [
+ 'children', //
+ 'dragStarting',
+ 'dragEnding',
+ 'htmltag',
+ 'scaling',
+ 'Document',
+ 'key',
+ 'onInput',
+ 'onClick',
+ '__proto__',
+ ]).omit;
+ const replacer = (match: string, expr: string) =>
// bcz: this executes a script to convert a property expression string: { script } into a value
(ScriptField.MakeFunction(expr, { this: Doc.name, scale: 'number' })?.script.run({ this: this.props.Document, scale: this.props.scaling }).result as string) || '';
Object.keys(divKeys).forEach((prop: string) => {
- const p = (this.props as any)[prop] as string;
+ const p = (this.props as unknown as { [key: string]: string })[prop] as string;
style[prop] = p?.replace(/{([^.'][^}']+)}/g, replacer);
});
const Tag = this.props.htmltag as keyof JSX.IntrinsicElements;
return (
- <Tag style={style} onClick={this.click} onInput={this.onInput as any}>
+ <Tag style={style} onClick={this.click} onInput={this.onInput}>
{this.props.children}
</Tag>
);
@@ -78,12 +89,12 @@ export class DocumentContentsView extends ObservableReactComponent<DocumentConte
/**
* Set of all available rendering componets for Docs (e.g., ImageBox, CollectionFreeFormView, etc)
*/
- private static Components: { [key: string]: any };
- public static Init(defaultLayoutString: string, components: { [key: string]: any }) {
+ private static Components: { [key: string]: DocumentContentsViewProps };
+ public static Init(defaultLayoutString: string, components: { [key: string]: DocumentContentsViewProps }) {
DocumentContentsView.DefaultLayoutString = defaultLayoutString;
DocumentContentsView.Components = components;
}
- constructor(props: any) {
+ constructor(props: DocumentContentsViewProps) {
super(props);
makeObservable(this);
}
@@ -132,13 +143,13 @@ export class DocumentContentsView extends ObservableReactComponent<DocumentConte
...this._props,
Document: this.layoutDoc ?? this._props.Document,
TemplateDataDocument: templateDataDoc instanceof Promise ? undefined : templateDataDoc,
- onClick: onClick as any as React.MouseEventHandler, // pass onClick script as if it were a real function -- it will be interpreted properly in the HTMLtag
- onInput: onInput as any as React.FormEventHandler,
+ onClick: onClick as unknown as React.MouseEventHandler, // pass onClick script as if it were a real function -- it will be interpreted properly in the HTMLtag
+ onInput: onInput as unknown as React.FormEventHandler,
};
return {
props: {
...OmitKeys(list, [...docOnlyProps], '').omit,
- },
+ } as BindingProps,
};
}
@@ -151,11 +162,11 @@ export class DocumentContentsView extends ObservableReactComponent<DocumentConte
let layoutFrame = this.layout;
// replace code content with a script >{content}< as in <HTMLdiv>{this.title}</HTMLdiv>
- const replacer = (match: any, prefix: string, expr: string, postfix: string) => prefix + ((ScriptField.MakeFunction(expr, { this: Doc.name })?.script.run({ this: this._props.Document }).result as string) || '') + postfix;
+ const replacer = (match: string, prefix: string, expr: string, postfix: string) => prefix + ((ScriptField.MakeFunction(expr, { this: Doc.name })?.script.run({ this: this._props.Document }).result as string) || '') + postfix;
layoutFrame = layoutFrame.replace(/(>[^{]*)[^=]\{([^.'][^<}]+)\}([^}]*<)/g, replacer);
// replace HTML<tag> with corresponding HTML tag as in: <HTMLdiv> becomes <HTMLtag Document={props.Document} htmltag='div'>
- const replacer2 = (match: any, p1: string) => `<HTMLtag Document={props.Document} scaling='${this._props.NativeDimScaling?.() || 1}' htmltag='${p1}'`;
+ const replacer2 = (match: string, p1: string) => `<HTMLtag Document={props.Document} scaling='${this._props.NativeDimScaling?.() || 1}' htmltag='${p1}'`;
layoutFrame = layoutFrame.replace(/<HTML([a-zA-Z0-9_-]+)/g, replacer2);
// replace /HTML<tag> with </HTMLdiv> as in: </HTMLdiv> becomes </HTMLtag>
@@ -194,6 +205,7 @@ export class DocumentContentsView extends ObservableReactComponent<DocumentConte
bindings={bindings}
jsx={layoutFrame}
showWarnings
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
onError={(test: any) => {
console.log('DocumentContentsView:' + test, bindings, layoutFrame);
}}
diff --git a/src/client/views/nodes/DocumentLinksButton.tsx b/src/client/views/nodes/DocumentLinksButton.tsx
index 0c5156339..c35a329c9 100644
--- a/src/client/views/nodes/DocumentLinksButton.tsx
+++ b/src/client/views/nodes/DocumentLinksButton.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, runInAction } from 'mobx';
@@ -55,7 +53,7 @@ export class DocumentLinksButton extends ObservableReactComponent<DocumentLinksB
@observable public static StartLinkView: DocumentView | undefined = undefined;
@observable public static AnnotationId: string | undefined = undefined;
@observable public static AnnotationUri: string | undefined = undefined;
- constructor(props: any) {
+ constructor(props: DocumentLinksButtonProps) {
super(props);
makeObservable(this);
}
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index 0f2905d5b..5ae232aa9 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -1,6 +1,7 @@
/* eslint-disable no-use-before-define */
/* eslint-disable react/jsx-props-no-spreading */
import { IconProp } from '@fortawesome/fontawesome-svg-core';
+import { Property } from 'csstype';
import { Howl } from 'howler';
import { IReactionDisposer, action, computed, makeObservable, observable, reaction, runInAction } from 'mobx';
import { observer } from 'mobx-react';
@@ -32,7 +33,7 @@ import { UPDATE_SERVER_CACHE } from '../../util/LinkManager';
import { ScriptingGlobals } from '../../util/ScriptingGlobals';
import { SearchUtil } from '../../util/SearchUtil';
import { SnappingManager } from '../../util/SnappingManager';
-import { UndoManager, undoBatch, undoable } from '../../util/UndoManager';
+import { UndoManager, undoable } from '../../util/UndoManager';
import { ContextMenu } from '../ContextMenu';
import { ContextMenuProps } from '../ContextMenuItem';
import { DocComponent } from '../DocComponent';
@@ -65,7 +66,7 @@ export interface DocumentViewProps extends FieldViewSharedProps {
hideLinkAnchors?: boolean;
hideLinkButton?: boolean;
hideCaptions?: boolean;
- contentPointerEvents?: 'none' | 'all' | undefined; // pointer events allowed for content of a document view. eg. set to "none" in menuSidebar for sharedDocs so that you can select a document, but not interact with its contents
+ contentPointerEvents?: Property.PointerEvents | undefined; // pointer events allowed for content of a document view. eg. set to "none" in menuSidebar for sharedDocs so that you can select a document, but not interact with its contents
dontCenter?: 'x' | 'y' | 'xy';
childHideDecorationTitle?: boolean;
childHideResizeHandles?: boolean;
@@ -116,7 +117,7 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
@observable _titleDropDownInnerWidth = 0; // width of menu dropdown when setting doc title
@observable _mounted = false; // turn off all pointer events if component isn't yet mounted (enables nested Docs in alternate UI textboxes that appear on hover which otherwise would grab focus from the text box, reverting to the original UI )
@observable _isContentActive: boolean | undefined = undefined;
- @observable _pointerEvents: 'none' | 'all' | 'visiblePainted' | undefined = undefined;
+ @observable _pointerEvents: Property.PointerEvents | undefined = undefined;
@observable _componentView: Opt<ViewBoxInterface<FieldViewProps>> = undefined; // needs to be accessed from DocumentView wrapper class
@observable _animateScaleTime: Opt<number> = undefined; // milliseconds for animating between views. defaults to 300 if not uset
@observable _animateScalingTo = 0;
@@ -216,7 +217,7 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
{ fireImmediately: true }
);
this._disposers.pointerevents = reaction(
- () => this.style(this.Document, StyleProp.PointerEvents) as 'all' | 'none' | 'visiblePainted' | undefined,
+ () => this.style(this.Document, StyleProp.PointerEvents) as Property.PointerEvents | undefined,
pointerevents => {
this._pointerEvents = pointerevents;
},
@@ -243,7 +244,7 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
Object.values(this._disposers).forEach(disposer => disposer?.());
}
- startDragging(x: number, y: number, dropAction: dropActionType, hideSource = false) {
+ startDragging(x: number, y: number, dropAction: dropActionType | undefined, hideSource = false) {
const docView = this._docView;
if (this._mainCont.current && docView) {
const views = DocumentView.Selected().filter(dv => dv.ContentDiv);
@@ -310,7 +311,8 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
const defaultDblclick = this._props.defaultDoubleClick?.() || this.Document.defaultDoubleClick;
undoable(() => {
if (this.onDoubleClickHdlr?.script) {
- this.onDoubleClickHdlr.script.run(scriptProps, console.log).result?.select && this._props.select(false);
+ const res = this.onDoubleClickHdlr.script.run(scriptProps, console.log).result as { select: boolean };
+ res.select && this._props.select(false);
} else if (!Doc.IsSystem(this.Document) && defaultDblclick !== 'ignore') {
this._props.addDocTab(this.Document, OpenWhere.lightboxAlways);
DocumentView.DeselectAll();
@@ -558,7 +560,7 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
if (!this.Document.isFolder) {
const templateDoc = Cast(this.Document[StrCast(this.Document.layout_fieldKey)], Doc, null);
const appearance = cm.findByDescription('Appearance...');
- const appearanceItems: ContextMenuProps[] = appearance && 'subitems' in appearance ? appearance.subitems : [];
+ const appearanceItems = appearance?.subitems ?? [];
if (this._props.renderDepth === 0) {
appearanceItems.splice(0, 0, { description: 'Open in Lightbox', event: () => DocumentView.SetLightboxDoc(this.Document), icon: 'external-link-alt' });
@@ -574,7 +576,7 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
// creates menu for the user to select how to reveal the flashcards
if (this.Document._layout_isFlashcard) {
const revealOptions = cm.findByDescription('Reveal Options');
- const revealItems: ContextMenuProps[] = revealOptions && 'subitems' in revealOptions ? revealOptions.subitems : [];
+ const revealItems = revealOptions?.subitems ?? [];
revealItems.push({ description: 'Hover', event: () => { this.layoutDoc[`_${this._props.fieldKey}_revealOp`] = 'hover'; }, icon: 'hand-point-up' }); // prettier-ignore
revealItems.push({ description: 'Flip', event: () => { this.layoutDoc[`_${this._props.fieldKey}_revealOp`] = 'flip'; }, icon: 'rotate' }); // prettier-ignore
!revealOptions && cm.addItem({ description: 'Reveal Options', addDivider: false, noexpand: true, subitems: revealItems, icon: 'layer-group' });
@@ -582,15 +584,16 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
if (this._props.bringToFront) {
const zorders = cm.findByDescription('ZOrder...');
- const zorderItems: ContextMenuProps[] = zorders && 'subitems' in zorders ? zorders.subitems : [];
+ const zorderItems = zorders?.subitems ?? [];
zorderItems.push({ description: 'Bring to Front', event: () => DocumentView.Selected().forEach(dv => dv._props.bringToFront?.(dv.Document, false)), icon: 'arrow-up' });
zorderItems.push({ description: 'Send to Back', event: () => DocumentView.Selected().forEach(dv => dv._props.bringToFront?.(dv.Document, true)), icon: 'arrow-down' });
zorderItems.push({
description: !this.layoutDoc._keepZDragged ? 'Keep ZIndex when dragged' : 'Allow ZIndex to change when dragged',
- event: undoBatch(
+ event: undoable(
action(() => {
this.layoutDoc._keepZWhenDragged = !this.layoutDoc._keepZWhenDragged;
- })
+ }),
+ 'set zIndex drag'
),
icon: 'hand-point-up',
});
@@ -599,7 +602,7 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
if (!Doc.IsSystem(this.Document) && !this.Document.hideClickBehaviors && !this._props.hideClickBehaviors) {
const existingOnClick = cm.findByDescription('OnClick...');
- const onClicks: ContextMenuProps[] = existingOnClick && 'subitems' in existingOnClick ? existingOnClick.subitems : [];
+ const onClicks = existingOnClick?.subitems ?? [];
onClicks.push({ description: 'Enter Portal', event: undoable(() => DocUtils.makeIntoPortal(this.Document, this.layoutDoc, this._allLinks), 'make into portal'), icon: 'window-restore' });
!Doc.noviceMode && onClicks.push({ description: 'Toggle Detail', event: this.setToggleDetail, icon: 'concierge-bell' });
@@ -624,7 +627,7 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
}
const more = cm.findByDescription('More...');
- const moreItems = more && 'subitems' in more ? more.subitems : [];
+ const moreItems = more?.subitems ?? [];
if (!Doc.IsSystem(this.Document)) {
if (!Doc.noviceMode) {
moreItems.push({ description: 'Make View of Metadata Field', event: () => Doc.MakeMetadataFieldTemplate(this.Document, this._props.TemplateDataDocument), icon: 'concierge-bell' });
@@ -648,7 +651,7 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
cm.addItem({ description: 'General...', noexpand: false, subitems: constantItems, icon: 'question' });
const help = cm.findByDescription('Help...');
- const helpItems: ContextMenuProps[] = help && 'subitems' in help ? help.subitems : [];
+ const helpItems = help?.subitems ?? [];
!Doc.noviceMode && helpItems.push({ description: 'Text Shortcuts Ctrl+/', event: () => this._props.addDocTab(Docs.Create.PdfDocument('/assets/cheat-sheet.pdf', { _width: 300, _height: 300 }), OpenWhere.addRight), icon: 'keyboard' });
!Doc.noviceMode && helpItems.push({ description: 'Print Document in Console', event: () => console.log(this.Document), icon: 'hand-point-right' });
!Doc.noviceMode && helpItems.push({ description: 'Print DataDoc in Console', event: () => console.log(this.dataDoc), icon: 'hand-point-right' });
@@ -844,7 +847,7 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
.map(field => Field.toKeyValueString(this.Document, field))
.join('\\')
}
- SetValue={undoBatch((input: string) => {
+ SetValue={undoable((input: string) => {
if (input?.startsWith('$')) {
if (this.layoutDoc.layout_showTitle) {
this.layoutDoc._layout_showTitle = input?.substring(1) ? input.substring(1) : undefined;
@@ -855,7 +858,7 @@ export class DocumentViewInternal extends DocComponent<FieldViewProps & Document
Doc.SetField(targetDoc, showTitle, input);
}
return true;
- })}
+ }, 'set title')}
/>
</div>
</div>
@@ -1245,7 +1248,7 @@ export class DocumentView extends DocComponent<DocumentViewProps>() {
public setToggleDetail = (scriptFieldKey = 'onClick') => this._docViewInternal?.setToggleDetail(scriptFieldKey);
public onContextMenu = (e?: React.MouseEvent, pageX?: number, pageY?: number) => this._docViewInternal?.onContextMenu?.(e, pageX, pageY);
public cleanupPointerEvents = () => this._docViewInternal?.cleanupPointerEvents();
- public startDragging = (x: number, y: number, dropAction: dropActionType, hideSource = false) => this._docViewInternal?.startDragging(x, y, dropAction, hideSource);
+ public startDragging = (x: number, y: number, dropAction: dropActionType | undefined, hideSource = false) => this._docViewInternal?.startDragging(x, y, dropAction, hideSource);
public showContextMenu = (pageX: number, pageY: number) => this._docViewInternal?.onContextMenu(undefined, pageX, pageY);
public toggleNativeDimensions = () => this._docViewInternal && this.Document.type !== DocumentType.INK && Doc.toggleNativeDimensions(this.layoutDoc, this.NativeDimScaling() ?? 1, this._props.PanelWidth(), this._props.PanelHeight());
@@ -1288,7 +1291,7 @@ export class DocumentView extends DocComponent<DocumentViewProps>() {
this.dataDoc.audioAnnoState = AudioAnnoState.playing;
break;
case AudioAnnoState.playing:
- this.dataDoc[AudioPlay]?.stop();
+ (this.dataDoc[AudioPlay] as Howl)?.stop();
this.dataDoc.audioAnnoState = AudioAnnoState.stopped;
break;
default:
diff --git a/src/client/views/nodes/EquationBox.tsx b/src/client/views/nodes/EquationBox.tsx
index 1f5c9b84b..fefe25764 100644
--- a/src/client/views/nodes/EquationBox.tsx
+++ b/src/client/views/nodes/EquationBox.tsx
@@ -1,4 +1,3 @@
-/* eslint-disable jsx-a11y/no-static-element-interactions */
import { action, makeObservable, reaction } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
@@ -50,8 +49,8 @@ export class EquationBox extends ViewBoxBaseComponent<FieldViewProps>() {
() => this._props.isSelected(),
selected => {
if (this._ref.current) {
- if (selected) this._ref.current.element.current.children[0].addEventListener('keydown', this.keyPressed, true);
- else this._ref.current.element.current.children[0].removeEventListener('keydown', this.keyPressed);
+ if (selected) (this._ref.current.element.current?.children[0] as HTMLElement).addEventListener('keydown', this.keyPressed, true);
+ else (this._ref.current.element.current?.children[0] as HTMLElement).removeEventListener('keydown', this.keyPressed);
}
},
{ fireImmediately: true }
@@ -60,8 +59,8 @@ export class EquationBox extends ViewBoxBaseComponent<FieldViewProps>() {
@action
keyPressed = (e: KeyboardEvent) => {
- const _height = DivHeight(this._ref.current!.element.current);
- const _width = DivWidth(this._ref.current!.element.current);
+ const _height = DivHeight(this._ref.current!.element?.current);
+ const _width = DivWidth(this._ref.current!.element?.current);
if (e.key === 'Enter') {
const nextEq = Docs.Create.EquationDocument(e.shiftKey ? StrCast(this.dataDoc.text) : 'x', {
title: '# math',
@@ -95,7 +94,7 @@ export class EquationBox extends ViewBoxBaseComponent<FieldViewProps>() {
};
updateSize = () => {
- const style = this._ref.current && getComputedStyle(this._ref.current.element.current);
+ const style = this._ref.current?.element.current && getComputedStyle(this._ref.current.element.current);
if (style?.width.endsWith('px') && style?.height.endsWith('px')) {
if (this.layoutDoc._nativeWidth) {
// if equation has been scaled then editing the expression must also edit the native dimensions to keep the aspect ratio
diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx
index fc59e9e26..dd71fd946 100644
--- a/src/client/views/nodes/FieldView.tsx
+++ b/src/client/views/nodes/FieldView.tsx
@@ -1,5 +1,6 @@
/* eslint-disable react/no-unused-prop-types */
/* eslint-disable react/require-default-props */
+import { Property } from 'csstype';
import { computed } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
@@ -95,7 +96,7 @@ export interface FieldViewSharedProps {
bringToFront?: (doc: Doc, sendToBack?: boolean) => void;
waitForDoubleClickToClick?: () => 'never' | 'always' | undefined;
defaultDoubleClick?: () => 'default' | 'ignore' | undefined;
- pointerEvents?: () => Opt<'none' | 'all' | 'visiblePainted'>;
+ pointerEvents?: () => Opt<Property.PointerEvents>;
suppressSetHeight?: boolean;
}
diff --git a/src/client/views/nodes/FontIconBox/ButtonInterface.ts b/src/client/views/nodes/FontIconBox/ButtonInterface.ts
deleted file mode 100644
index 0d0d7b1c3..000000000
--- a/src/client/views/nodes/FontIconBox/ButtonInterface.ts
+++ /dev/null
@@ -1,12 +0,0 @@
-import { IconProp } from '@fortawesome/fontawesome-svg-core';
-import { Doc } from '../../../../fields/Doc';
-import { ButtonType } from './FontIconBox';
-
-export interface IButtonProps {
- type: string | ButtonType;
- Document: Doc;
- label: any;
- icon: IconProp;
- color: string;
- backgroundColor: string;
-}
diff --git a/src/client/views/nodes/FontIconBox/FontIconBox.tsx b/src/client/views/nodes/FontIconBox/FontIconBox.tsx
index ffb668b03..f2f7f39bb 100644
--- a/src/client/views/nodes/FontIconBox/FontIconBox.tsx
+++ b/src/client/views/nodes/FontIconBox/FontIconBox.tsx
@@ -73,12 +73,12 @@ export class FontIconBox extends ViewBoxBaseComponent<ButtonProps>() {
Icon = (color: string, iconFalse?: boolean) => {
let icon;
if (iconFalse) {
- icon = StrCast(this.dataDoc[this.fieldKey ?? 'iconFalse'] ?? this.dataDoc.icon, 'user') as any;
+ icon = StrCast(this.dataDoc[this.fieldKey ?? 'iconFalse'] ?? this.dataDoc.icon, 'user') as IconProp;
if (icon) return <FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={icon} color={color} />;
return null;
}
- icon = StrCast(this.dataDoc[this.fieldKey ?? 'icon'] ?? this.dataDoc.icon, 'user') as any;
- return !icon ? null : icon === 'pres-trail' ? TrailsIcon(color) : <FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={icon} color={color} />;
+ icon = StrCast(this.dataDoc[this.fieldKey ?? 'icon'] ?? this.dataDoc.icon, 'user') as IconProp;
+ return !icon ? null : icon === ('pres-trail' as IconProp) ? TrailsIcon(color) : <FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={icon} color={color} />;
};
@computed get dropdown() {
return BoolCast(this.Document.dropDownOpen);
@@ -117,7 +117,7 @@ export class FontIconBox extends ViewBoxBaseComponent<ButtonProps>() {
break;
} // prettier-ignore
const numScript = (value?: number) => ScriptCast(this.Document.script).script.run({ this: this.Document, value, _readOnly_: value === undefined });
- const color = this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.Color);
+ const color = this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.Color) as string;
// Script for checking the outcome of the toggle
const checkResult = Number(Number(numScript().result ?? 0).toPrecision(NumCast(this.dataDoc.numPrecision, 3)));
@@ -142,7 +142,7 @@ export class FontIconBox extends ViewBoxBaseComponent<ButtonProps>() {
setupMoveUpEvents(
this,
e,
- () => ScriptCast(this.Document.onDragScript)?.script.run({ this: this.Document, value: { doc: value, e } }).result,
+ () => ScriptCast(this.Document.onDragScript)?.script.run({ this: this.Document, value: { doc: value, e } }).result as boolean,
emptyFunction,
emptyFunction
); // prettier-ignore
@@ -157,11 +157,11 @@ export class FontIconBox extends ViewBoxBaseComponent<ButtonProps>() {
let noviceList: string[] = [];
let text: string | undefined;
- let getStyle: (val: string) => any = () => {};
+ let getStyle: (val: string) => { [key: string]: string } = () => ({});
let icon: IconProp = 'caret-down';
const isViewDropdown = script?.script.originalScript.startsWith('{ return setView');
if (isViewDropdown) {
- const selected = Array.from(script?.script.run({ _readOnly_: true }).result) as Doc[];
+ const selected = Array.from(script?.script.run({ _readOnly_: true }).result as Doc[]);
// const selected = DocumentView.SelectedDocs();
if (selected.lastElement()) {
if (StrCast(selected.lastElement().type) === DocumentType.COL) {
@@ -190,7 +190,7 @@ export class FontIconBox extends ViewBoxBaseComponent<ButtonProps>() {
}
noviceList = [CollectionViewType.Freeform, CollectionViewType.Schema, CollectionViewType.Carousel3D, CollectionViewType.Stacking, CollectionViewType.NoteTaking];
} else {
- text = script?.script.run({ this: this.Document, value: '', _readOnly_: true }).result;
+ text = script?.script.run({ this: this.Document, value: '', _readOnly_: true }).result as string;
// text = StrCast((RichTextMenu.Instance?.TextView?.EditorView ? RichTextMenu.Instance : Doc.UserDoc()).fontFamily);
getStyle = (val: string) => ({ fontFamily: val });
}
@@ -231,8 +231,8 @@ export class FontIconBox extends ViewBoxBaseComponent<ButtonProps>() {
* Color button
*/
@computed get colorButton() {
- const color = this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.Color);
- const curColor = this.colorScript?.script.run({ this: this.Document, value: undefined, _readOnly_: true }).result ?? 'transparent';
+ const color = this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.Color) as string;
+ const curColor = (this.colorScript?.script.run({ this: this.Document, value: undefined, _readOnly_: true }).result as string) ?? 'transparent';
const tooltip: string = StrCast(this.Document.toolTip);
return (
@@ -251,7 +251,7 @@ export class FontIconBox extends ViewBoxBaseComponent<ButtonProps>() {
type={Type.PRIM}
color={color}
background={SnappingManager.userBackgroundColor}
- icon={this.Icon(color)!}
+ icon={this.Icon(color) ?? undefined}
tooltip={tooltip}
label={this.label}
/>
@@ -262,9 +262,9 @@ export class FontIconBox extends ViewBoxBaseComponent<ButtonProps>() {
const tooltip: string = StrCast(this.Document.toolTip);
const script = ScriptCast(this.Document.onClick)?.script;
- const toggleStatus = script?.run({ this: this.Document, self: this.Document, value: undefined, _readOnly_: true }).result;
+ const toggleStatus = script?.run({ this: this.Document, self: this.Document, value: undefined, _readOnly_: true }).result as boolean;
// Colors
- const color = this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.Color);
+ const color = this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.Color) as string;
const items = DocListCast(this.dataDoc.data);
const multiDoc = this.Document;
return (
@@ -272,13 +272,13 @@ export class FontIconBox extends ViewBoxBaseComponent<ButtonProps>() {
tooltip={`Toggle ${tooltip}`}
type={Type.PRIM}
color={color}
- onPointerDown={e => script && !toggleStatus && setupMoveUpEvents(this, e, returnFalse, emptyFunction, e => script.run({ this: multiDoc, value: undefined, _readOnly_: false }))}
+ onPointerDown={e => script && !toggleStatus && setupMoveUpEvents(this, e, returnFalse, emptyFunction, () => script.run({ this: multiDoc, value: undefined, _readOnly_: false }))}
isToggle={script ? true : false}
toggleStatus={toggleStatus}
//background={SnappingManager.userBackgroundColor}
label={this.label}
items={DocListCast(this.dataDoc.data).map(item => ({
- icon: <FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={StrCast(item.icon) as any} color={color} />,
+ icon: <FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon={StrCast(item.icon) as IconProp} color={color} />,
tooltip: StrCast(item.toolTip),
val: StrCast(item.toolType),
}))}
@@ -300,9 +300,9 @@ export class FontIconBox extends ViewBoxBaseComponent<ButtonProps>() {
const script = ScriptCast(this.Document.onClick);
const double = ScriptCast(this.Document.onDoubleClick);
- const toggleStatus = script?.script.run({ this: this.Document, value: undefined, _readOnly_: true }).result ?? false;
+ const toggleStatus = (script?.script.run({ this: this.Document, value: undefined, _readOnly_: true }).result as boolean) ?? false;
// Colors
- const color = this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.Color);
+ const color = this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.Color) as string;
// const backgroundColor = this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.BackgroundColor);
return (
@@ -337,30 +337,30 @@ export class FontIconBox extends ViewBoxBaseComponent<ButtonProps>() {
* Default
*/
@computed get defaultButton() {
- const color = this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.Color);
- const tooltip: string = StrCast(this.Document.toolTip);
+ const color = this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.Color) as string;
+ const tooltip = StrCast(this.Document.toolTip);
- return <IconButton tooltip={tooltip} icon={this.Icon(color)!} label={this.label} />;
+ return <IconButton tooltip={tooltip} icon={this.Icon(color) ?? undefined} label={this.label} />;
}
@computed get editableText() {
const script = ScriptCast(this.Document.script);
const checkResult = script?.script.run({ this: this.Document, value: '', _readOnly_: true }).result;
- const setValue = (value: string): boolean => script?.script.run({ this: this.Document, value, _readOnly_: false }).result;
+ const setValue = (value: string) => script?.script.run({ this: this.Document, value, _readOnly_: false }).result as boolean;
return (
<div className="menuButton editableText">
<FontAwesomeIcon className={`fontIconBox-icon-${this.type}`} icon="lock" />
<div style={{ width: 'calc(100% - .875em)', paddingLeft: '4px' }}>
- <EditableView GetValue={() => script?.script.run({ this: this.Document, value: '', _readOnly_: true }).result} SetValue={setValue} oneLine contents={checkResult} />
+ <EditableView GetValue={() => script?.script.run({ this: this.Document, value: '', _readOnly_: true }).result as string} SetValue={setValue} oneLine contents={checkResult} />
</div>
</div>
);
}
renderButton = () => {
- const color = this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.Color);
+ const color = this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.Color) as string;
const tooltip = StrCast(this.Document.toolTip);
const scriptFunc = () => ScriptCast(this.Document.onClick)?.script.run({ this: this.Document, _readOnly_: false });
const btnProps = { tooltip, icon: this.Icon(color)!, label: this.label };
diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx
index ce7552047..51dd494da 100644
--- a/src/client/views/nodes/ImageBox.tsx
+++ b/src/client/views/nodes/ImageBox.tsx
@@ -35,6 +35,7 @@ import { FieldView, FieldViewProps } from './FieldView';
import { FocusViewOptions } from './FocusViewOptions';
import './ImageBox.scss';
import { OpenWhere } from './OpenWhere';
+import { SnappingManager } from '../../util/SnappingManager';
export class ImageEditorData {
// eslint-disable-next-line no-use-before-define
@@ -73,7 +74,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
private _marqueeref = React.createRef<MarqueeAnnotator>();
private _mainCont: React.RefObject<HTMLDivElement> = React.createRef();
private _annotationLayer: React.RefObject<HTMLDivElement> = React.createRef();
- @observable _savedAnnotations = new ObservableMap<number, (HTMLDivElement & { marqueeing?: boolean})[]>();
+ @observable _savedAnnotations = new ObservableMap<number, (HTMLDivElement & { marqueeing?: boolean })[]>();
@observable _curSuffix = '';
@observable _error = '';
@observable _isHovering = false; // flag to switch between primary and alternate images on hover
@@ -328,7 +329,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
})
}
style={{
- display: (this._props.isContentActive() !== false && DragManager.DocDragData?.canEmbed) || this.dataDoc[this.fieldKey + '_alternates'] ? 'block' : 'none',
+ display: (this._props.isContentActive() !== false && SnappingManager.CanEmbed) || this.dataDoc[this.fieldKey + '_alternates'] ? 'block' : 'none',
width: 'min(10%, 25px)',
height: 'min(10%, 25px)',
background: usePath === undefined ? 'white' : usePath === 'alternate' ? 'black' : 'gray',
@@ -346,7 +347,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
const defaultUrl = new URL(ClientUtils.prepend('/assets/unknown-file-icon-hi.png'));
const altpaths =
alts
- ?.map(doc => (doc instanceof Doc ? ImageCast(doc[Doc.LayoutFieldKey(doc)])?.url ?? defaultUrl : defaultUrl))
+ ?.map(doc => (doc instanceof Doc ? (ImageCast(doc[Doc.LayoutFieldKey(doc)])?.url ?? defaultUrl) : defaultUrl))
.filter(url => url)
.map(url => this.choosePath(url)) ?? []; // acc ess the primary layout data of the alternate documents
const paths = field ? [this.choosePath(field.url), ...altpaths] : altpaths;
@@ -356,7 +357,7 @@ export class ImageBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
@computed get content() {
TraceMobx();
- const backColor = DashColor(this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.BackgroundColor) as string ?? Colors.WHITE);
+ const backColor = DashColor((this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.BackgroundColor) as string) ?? Colors.WHITE);
const backAlpha = backColor.red() === 0 && backColor.green() === 0 && backColor.blue() === 0 ? backColor.alpha() : 1;
const srcpath = this.layoutDoc.hideImage ? '' : this.paths[0];
const fadepath = this.layoutDoc.hideImage ? '' : this.paths.lastElement();
diff --git a/src/client/views/nodes/KeyValueBox.tsx b/src/client/views/nodes/KeyValueBox.tsx
index 66e210c03..9e77e0973 100644
--- a/src/client/views/nodes/KeyValueBox.tsx
+++ b/src/client/views/nodes/KeyValueBox.tsx
@@ -1,4 +1,3 @@
-/* eslint-disable jsx-a11y/control-has-associated-label */
import { action, computed, makeObservable, observable } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
@@ -35,7 +34,7 @@ export class KeyValueBox extends ViewBoxBaseComponent<FieldViewProps>() {
public static LayoutString() {
return FieldView.LayoutString(KeyValueBox, 'data');
}
- constructor(props: any) {
+ constructor(props: FieldViewProps) {
super(props);
makeObservable(this);
}
@@ -88,7 +87,7 @@ export class KeyValueBox extends ViewBoxBaseComponent<FieldViewProps>() {
const type: 'computed' | 'script' | false = rawvalue.startsWith(':=') ? 'computed' : rawvalue.startsWith('$=') ? 'script' : false;
rawvalue = type ? rawvalue.substring(2) : rawvalue;
rawvalue = rawvalue.replace(/.*\(\((.*)\)\)/, 'dashCallChat(_setCacheResult_, this, `$1`)');
- const value = ["'", '"', '`'].includes(rawvalue.length ? rawvalue[0] : '') || !isNaN(rawvalue as any) ? rawvalue : '`' + rawvalue + '`';
+ const value = ["'", '"', '`'].includes(rawvalue.length ? rawvalue[0] : '') || !isNaN(+rawvalue) ? rawvalue : '`' + rawvalue + '`';
let script = ScriptField.CompileScript(rawvalue, {}, true, undefined, DocumentIconContainer.getTransformer());
if (!script.compiled) {
@@ -116,7 +115,7 @@ export class KeyValueBox extends ViewBoxBaseComponent<FieldViewProps>() {
if (key) target[key] = script.originalScript;
return false;
}
- field === undefined && (field = res.result instanceof Array ? new List<any>(res.result) : res.result);
+ field === undefined && (field = res.result instanceof Array ? new List<FieldType>(res.result) : (res.result as FieldType));
}
}
if (!key) return false;
@@ -165,7 +164,6 @@ export class KeyValueBox extends ViewBoxBaseComponent<FieldViewProps>() {
const rows: JSX.Element[] = [];
let i = 0;
- const self = this;
const keys = Object.keys(ids).slice();
// for (const key of [...keys.filter(id => id !== 'layout' && !id.includes('_')).sort(), ...keys.filter(id => id === 'layout' || id.includes('_')).sort()]) {
const sortedKeys = keys.sort((a: string, b: string) => {
@@ -184,12 +182,12 @@ export class KeyValueBox extends ViewBoxBaseComponent<FieldViewProps>() {
addDocTab={this._props.addDocTab}
PanelWidth={this._props.PanelWidth}
PanelHeight={this.rowHeight}
- ref={(function () {
+ ref={(() => {
let oldEl: KeyValuePair | undefined;
return (el: KeyValuePair) => {
- if (oldEl) self.rows.splice(self.rows.indexOf(oldEl), 1);
+ if (oldEl) this.rows.splice(this.rows.indexOf(oldEl), 1);
oldEl = el;
- if (el) self.rows.push(el);
+ if (el) this.rows.push(el);
};
})()}
keyWidth={100 - this._splitPercentage}
diff --git a/src/client/views/nodes/KeyValuePair.tsx b/src/client/views/nodes/KeyValuePair.tsx
index 0956be3e9..3023716b1 100644
--- a/src/client/views/nodes/KeyValuePair.tsx
+++ b/src/client/views/nodes/KeyValuePair.tsx
@@ -1,4 +1,3 @@
-/* eslint-disable jsx-a11y/control-has-associated-label */
import { Tooltip } from '@mui/material';
import { action, makeObservable, observable } from 'mobx';
import { observer } from 'mobx-react';
@@ -9,7 +8,7 @@ import { Doc, Field } from '../../../fields/Doc';
import { DocCast } from '../../../fields/Types';
import { DocumentOptions, FInfo } from '../../documents/Documents';
import { Transform } from '../../util/Transform';
-import { undoBatch } from '../../util/UndoManager';
+import { undoable } from '../../util/UndoManager';
import { ContextMenu } from '../ContextMenu';
import { EditableView } from '../EditableView';
import { ObservableReactComponent } from '../ObservableReactComponent';
@@ -34,7 +33,7 @@ export class KeyValuePair extends ObservableReactComponent<KeyValuePairProps> {
@observable private isPointerOver = false;
@observable public isChecked = false;
private checkbox = React.createRef<HTMLInputElement>();
- constructor(props: any) {
+ constructor(props: KeyValuePairProps) {
super(props);
makeObservable(this);
}
@@ -91,11 +90,11 @@ export class KeyValuePair extends ObservableReactComponent<KeyValuePairProps> {
type="button"
style={hover}
className="keyValuePair-td-key-delete"
- onClick={undoBatch(() => {
+ onClick={undoable(() => {
if (Object.keys(this._props.doc).indexOf(this._props.keyName) !== -1) {
delete this._props.doc[this._props.keyName];
} else delete DocCast(this._props.doc.proto)?.[this._props.keyName];
- })}>
+ }, 'set key value')}>
X
</button>
<input className="keyValuePair-td-key-check" type="checkbox" style={hover} onChange={this.handleCheck} ref={this.checkbox} />
diff --git a/src/client/views/nodes/LinkBox.tsx b/src/client/views/nodes/LinkBox.tsx
index 8d6ae9f73..4d9d2460e 100644
--- a/src/client/views/nodes/LinkBox.tsx
+++ b/src/client/views/nodes/LinkBox.tsx
@@ -27,6 +27,7 @@ export class LinkBox extends ViewBoxBaseComponent<FieldViewProps>() {
public static LayoutString(fieldKey: string = 'link') {
return FieldView.LayoutString(LinkBox, fieldKey);
}
+ _hackToSeeIfDeleted: NodeJS.Timeout | undefined;
_disposers: { [name: string]: IReactionDisposer } = {};
@observable _forceAnimate: number = 0; // forces xArrow to animate when a transition animation is detected on something that affects an anchor
@observable _hide = false; // don't render if anchor is not visible since that breaks xAnchor
@@ -43,7 +44,6 @@ export class LinkBox extends ViewBoxBaseComponent<FieldViewProps>() {
const anchor = anch?.layout_unrendered ? DocCast(anch.annotationOn) : anch;
return DocumentView.getDocumentView(anchor, this.DocumentView?.().containerViewPath?.().lastElement());
};
- _hackToSeeIfDeleted: any;
componentWillUnmount() {
this._hackToSeeIfDeleted && clearTimeout(this._hackToSeeIfDeleted);
Object.keys(this._disposers).forEach(key => this._disposers[key]());
@@ -68,7 +68,7 @@ export class LinkBox extends ViewBoxBaseComponent<FieldViewProps>() {
let a1 = a && document.getElementById(a.ViewGuid);
let a2 = b && document.getElementById(b.ViewGuid);
// test whether the anchors themselves are hidden,...
- if (!a1 || !a2 || (a?.ContentDiv as any)?.hidden || (b?.ContentDiv as any)?.hidden) this._hide = true;
+ if (!a1 || !a2 || a?.ContentDiv?.hidden || b?.ContentDiv?.hidden) this._hide = true;
else {
// .. or whether any of their DOM parents are hidden
for (; a1 && !a1.hidden; a1 = a1.parentElement);
@@ -151,11 +151,11 @@ export class LinkBox extends ViewBoxBaseComponent<FieldViewProps>() {
this._forceAnimate += 0.01;
})
); // this forces an update during a transition animation
- const highlight = this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.Highlighting);
+ const highlight = this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.Highlighting) as { highlightStyle: string; highlightColor: string; highlightIndex: number; highlightStroke: boolean };
const highlightColor = highlight?.highlightIndex ? highlight?.highlightColor : undefined;
- const color = this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.Color);
- const fontFamily = this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.FontFamily);
- const fontSize = this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.FontSize);
+ const color = this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.Color) as string;
+ const fontFamily = this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.FontFamily) as string;
+ const fontSize = this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.FontSize) as number;
const fontColor = (c => (c !== 'transparent' ? c : undefined))(StrCast(this.layoutDoc.link_fontColor));
// eslint-disable-next-line camelcase
const { stroke_markerScale: strokeMarkerScale, stroke_width: strokeRawWidth, stroke_startMarker: strokeStartMarker, stroke_endMarker: strokeEndMarker, stroke_dash: strokeDash } = this.Document;
@@ -248,7 +248,7 @@ export class LinkBox extends ViewBoxBaseComponent<FieldViewProps>() {
2
);
return (
- <div className={`linkBox-container${this._props.isContentActive() ? '-interactive' : ''}`} style={{ background: this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.BackgroundColor) }}>
+ <div className={`linkBox-container${this._props.isContentActive() ? '-interactive' : ''}`} style={{ background: this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.BackgroundColor) as string }}>
<ComparisonBox
// eslint-disable-next-line react/jsx-props-no-spreading
{...this.props} //
diff --git a/src/client/views/nodes/LinkDocPreview.tsx b/src/client/views/nodes/LinkDocPreview.tsx
index 8f29600f6..10ff86a38 100644
--- a/src/client/views/nodes/LinkDocPreview.tsx
+++ b/src/client/views/nodes/LinkDocPreview.tsx
@@ -67,7 +67,7 @@ export class LinkDocPreview extends ObservableReactComponent<LinkDocPreviewProps
@observable _linkSrc: Opt<Doc> = undefined;
@observable _toolTipText = '';
@observable _hrefInd = 0;
- constructor(props: any) {
+ constructor(props: LinkDocPreviewProps) {
super(props);
makeObservable(this);
}
@@ -104,7 +104,7 @@ export class LinkDocPreview extends ObservableReactComponent<LinkDocPreviewProps
}
onPointerDown = (e: PointerEvent) => {
- !this._linkDocRef.current?.contains(e.target as any) && LinkInfo.Clear(); // close preview when not clicking anywhere other than the info bar of the preview
+ !this._linkDocRef.current?.contains(e.target as HTMLElement) && LinkInfo.Clear(); // close preview when not clicking anywhere other than the info bar of the preview
};
@action
@@ -144,7 +144,7 @@ export class LinkDocPreview extends ObservableReactComponent<LinkDocPreviewProps
this._linkSrc = anchor;
const linkTarget = Doc.getOppositeAnchor(this._linkDoc, this._linkSrc);
this._markerTargetDoc = linkTarget;
- this._targetDoc = /* linkTarget?.type === DocumentType.MARKER && */ linkTarget?.annotationOn ? Cast(linkTarget.annotationOn, Doc, null) ?? linkTarget : linkTarget;
+ this._targetDoc = /* linkTarget?.type === DocumentType.MARKER && */ linkTarget?.annotationOn ? (Cast(linkTarget.annotationOn, Doc, null) ?? linkTarget) : linkTarget;
}
if (LinkInfo.Instance?.LinkInfo?.noPreview || this._linkSrc?.followLinkToggle || this._markerTargetDoc?.type === DocumentType.PRES) this.followLink();
}
diff --git a/src/client/views/nodes/LoadingBox.tsx b/src/client/views/nodes/LoadingBox.tsx
index 5f343bdfe..325ab18b4 100644
--- a/src/client/views/nodes/LoadingBox.tsx
+++ b/src/client/views/nodes/LoadingBox.tsx
@@ -39,7 +39,7 @@ export class LoadingBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
return FieldView.LayoutString(LoadingBox, fieldKey);
}
- _timer: any;
+ _timer: NodeJS.Timeout | undefined;
@observable progress = '';
componentDidMount() {
if (!Doc.CurrentlyLoading?.includes(this.Document)) {
diff --git a/src/client/views/nodes/MapBox/MapBox.tsx b/src/client/views/nodes/MapBox/MapBox.tsx
index d7687e03e..c66f7c726 100644
--- a/src/client/views/nodes/MapBox/MapBox.tsx
+++ b/src/client/views/nodes/MapBox/MapBox.tsx
@@ -1,5 +1,3 @@
-/* eslint-disable jsx-a11y/no-static-element-interactions */
-/* eslint-disable jsx-a11y/click-events-have-key-events */
import { IconLookup, faCircleXmark, faGear, faPause, faPlay, faRotate } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { Checkbox, FormControlLabel, TextField } from '@mui/material';
@@ -481,8 +479,8 @@ export class MapBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
console.log('deleting');
if (this._selectedPinOrRoute) {
// Removes filter
- Doc.setDocFilter(this.Document, 'latitude', this._selectedPinOrRoute.latitude, 'remove');
- Doc.setDocFilter(this.Document, 'longitude', this._selectedPinOrRoute.longitude, 'remove');
+ Doc.setDocFilter(this.Document, 'latitude', NumCast(this._selectedPinOrRoute.latitude), 'remove');
+ Doc.setDocFilter(this.Document, 'longitude', NumCast(this._selectedPinOrRoute.longitude), 'remove');
Doc.setDocFilter(this.Document, LinkedTo, `mapPin=${Field.toScriptString(DocCast(this._selectedPinOrRoute))}`, 'remove');
this.removePushpinOrRoute(this._selectedPinOrRoute);
@@ -1152,7 +1150,7 @@ export class MapBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
_textRef = React.createRef<any>();
render() {
const scale = this._props.NativeDimScaling?.() || 1;
- const parscale = scale === 1 ? 1 : this.ScreenToLocalBoxXf().Scale ?? 1;
+ const parscale = scale === 1 ? 1 : (this.ScreenToLocalBoxXf().Scale ?? 1);
return (
<div className="mapBox" ref={this._ref}>
diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx
index 8db68ddfe..c03694dd9 100644
--- a/src/client/views/nodes/PDFBox.tsx
+++ b/src/client/views/nodes/PDFBox.tsx
@@ -1,5 +1,3 @@
-/* eslint-disable jsx-a11y/no-static-element-interactions */
-/* eslint-disable jsx-a11y/control-has-associated-label */
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { action, computed, IReactionDisposer, makeObservable, observable, reaction, runInAction } from 'mobx';
import { observer } from 'mobx-react';
@@ -76,7 +74,7 @@ export class PDFBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
});
else if (PDFBox.pdfpromise.get(this.pdfUrl.url.href))
PDFBox.pdfpromise.get(this.pdfUrl.url.href)?.then(
- action((pdf: any) => {
+ action(pdf => {
this._pdf = pdf;
})
);
@@ -108,7 +106,8 @@ export class PDFBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
};
crop = (region: Doc | undefined, addCrop?: boolean) => {
- if (!region) return undefined;
+ const docViewContent = this.DocumentView?.().ContentDiv;
+ if (!region || !docViewContent) return undefined;
const cropping = Doc.MakeCopy(region, true);
cropping.layout_unrendered = false; // text selection have this
cropping.text_inlineAnnotations = undefined; // text selections have this -- it causes them not to be rendered.
@@ -120,7 +119,6 @@ export class PDFBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
regionData.followLinkToggle = true;
this.addDocument(region);
- const docViewContent = this.DocumentView?.().ContentDiv!;
const newDiv = docViewContent.cloneNode(true) as HTMLDivElement;
newDiv.style.width = NumCast(this.layoutDoc._width).toString();
newDiv.style.height = NumCast(this.layoutDoc._height).toString();
@@ -162,7 +160,7 @@ export class PDFBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
(NumCast(region.x) * this._props.PanelWidth()) / NumCast(this.dataDoc[this.fieldKey + '_nativeWidth']),
4
)
- .then((dataUrl: any) => {
+ .then(dataUrl => {
ClientUtils.convertDataUri(dataUrl, region[Id]).then(returnedfilename =>
setTimeout(
action(() => {
@@ -172,7 +170,7 @@ export class PDFBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
)
);
})
- .catch((error: any) => {
+ .catch(error => {
console.error('oops, something went wrong!', error);
});
@@ -181,9 +179,10 @@ export class PDFBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
updateIcon = () => {
// currently we render pdf icons as text labels
- const docViewContent = this.DocumentView?.().ContentDiv!;
+ const docViewContent = this.DocumentView?.().ContentDiv;
const filename = this.layoutDoc[Id] + '-icon' + new Date().getTime();
this._pdfViewer?._mainCont.current &&
+ docViewContent &&
UpdateIcon(
filename,
docViewContent,
@@ -475,6 +474,7 @@ export class PDFBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
const cm = ContextMenu.Instance;
const options = cm.findByDescription('Options...');
const optionItems: ContextMenuProps[] = options && 'subitems' in options ? 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" });
@@ -656,7 +656,7 @@ export class PDFBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
else {
if (!PDFBox.pdfpromise.get(href)) PDFBox.pdfpromise.set(href, Pdfjs.getDocument(href).promise);
PDFBox.pdfpromise.get(href)?.then(
- action((pdf: any) => {
+ action(pdf => {
PDFBox.pdfcache.set(href, (this._pdf = pdf));
})
);
diff --git a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
index f88eb3bca..31a1a398b 100644
--- a/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
+++ b/src/client/views/nodes/PhysicsBox/PhysicsSimulationBox.tsx
@@ -1,8 +1,5 @@
/* eslint-disable camelcase */
-/* eslint-disable jsx-a11y/control-has-associated-label */
/* eslint-disable @typescript-eslint/no-unused-vars */
-/* eslint-disable jsx-a11y/no-noninteractive-element-interactions */
-/* eslint-disable jsx-a11y/click-events-have-key-events */
/* eslint-disable react/no-array-index-key */
/* eslint-disable react/jsx-props-no-spreading */
/* eslint-disable no-return-assign */
@@ -1009,7 +1006,7 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
<Dialog maxWidth="sm" fullWidth open={BoolCast(this.dataDoc.hintDialogueOpen)} onClose={() => (this.dataDoc.hintDialogueOpen = false)}>
<DialogTitle>Hints</DialogTitle>
<DialogContent>
- {this.selectedQuestion.hints?.map((hint: any, index: number) => (
+ {this.selectedQuestion.hints?.map((hint: { description: string; content: string }, index: number) => (
<div key={index}>
<DialogContentText>
<details>
@@ -1985,7 +1982,13 @@ export class PhysicsSimulationBox extends ViewBoxAnnotatableComponent<FieldViewP
}
Docs.Prototypes.TemplateMap.set(DocumentType.SIMULATION, {
- data: '',
layout: { view: PhysicsSimulationBox, dataField: 'data' },
- options: { acl: '', _width: 1000, _height: 800, mass1: '', mass2: '', layout_nativeDimEditable: true, position: '', acceleration: '', pendulum: '', spring: '', wedge: '', simulation: '', review: '', systemIcon: 'BsShareFill' },
+ options: {
+ acl: '',
+ _width: 1000,
+ _height: 800,
+ _layout_nativeDimEditable: true,
+ systemIcon: 'BsShareFill',
+ // mass1: '', mass2: '', position: '', acceleration: '', pendulum: '', spring: '', wedge: '', simulation: '', review: ''
+ },
});
diff --git a/src/client/views/nodes/RecordingBox/RecordingBox.tsx b/src/client/views/nodes/RecordingBox/RecordingBox.tsx
index 07381c7d0..7ba313e92 100644
--- a/src/client/views/nodes/RecordingBox/RecordingBox.tsx
+++ b/src/client/views/nodes/RecordingBox/RecordingBox.tsx
@@ -55,8 +55,7 @@ export class RecordingBox extends ViewBoxBaseComponent<FieldViewProps>() {
this.dataDoc[this._props.fieldKey] = new VideoField(this.result.accessPaths.client);
// stringify the presentation and store it
if (presentation?.movements) {
- const presCopy = { ...presentation };
- presCopy.movements = presentation.movements.map(movement => ({ ...movement, doc: movement.doc[Id] })) as any;
+ const presCopy = { ...presentation, movements: presentation.movements.map(movement => ({ ...movement, doc: (movement.doc as Doc)[Id] })) };
this.dataDoc[this.fieldKey + '_presentation'] = JSON.stringify(presCopy);
}
};
@@ -210,7 +209,7 @@ ScriptingGlobals.add(function getCurrentRecording() {
});
// eslint-disable-next-line prefer-arrow-callback
ScriptingGlobals.add(function getWorkspaceRecordings() {
- return new List<any>(['Record Workspace', `Record Webcam`, ...DocListCast(Doc.UserDoc().workspaceRecordings)]);
+ return new List<string | Doc>(['Record Workspace', `Record Webcam`, ...DocListCast(Doc.UserDoc().workspaceRecordings)]);
});
// eslint-disable-next-line prefer-arrow-callback
ScriptingGlobals.add(function isWorkspaceRecording() {
diff --git a/src/client/views/nodes/ScreenshotBox.tsx b/src/client/views/nodes/ScreenshotBox.tsx
index 9ef1071f7..6289470b6 100644
--- a/src/client/views/nodes/ScreenshotBox.tsx
+++ b/src/client/views/nodes/ScreenshotBox.tsx
@@ -20,7 +20,7 @@ import { DocumentType } from '../../documents/DocumentTypes';
import { Docs } from '../../documents/Documents';
import { CaptureManager } from '../../util/CaptureManager';
import { SettingsManager } from '../../util/SettingsManager';
-import { TrackMovements } from '../../util/TrackMovements';
+import { Movement, TrackMovements } from '../../util/TrackMovements';
import { ContextMenu } from '../ContextMenu';
import { ViewBoxAnnotatableComponent } from '../DocComponent';
import { DocViewUtils } from '../DocViewUtils';
@@ -31,10 +31,11 @@ import { FieldView, FieldViewProps } from './FieldView';
import './ScreenshotBox.scss';
import { VideoBox } from './VideoBox';
import { FormattedTextBox } from './formattedText/FormattedTextBox';
+import { IconProp } from '@fortawesome/fontawesome-svg-core';
-declare class MediaRecorder {
- constructor(e: any, options?: any); // whatever MediaRecorder has
-}
+// declare class MediaRecorder {
+// constructor(e: any, options?: any); // whatever MediaRecorder has
+// }
// interface VideoTileProps {
// raised: { coord: Vector2, off: Vector3 }[];
@@ -117,8 +118,8 @@ export class ScreenshotBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
public static LayoutString(fieldKey: string) {
return FieldView.LayoutString(ScreenshotBox, fieldKey);
}
- private _audioRec: any;
- private _videoRec: any;
+ private _audioRec: MediaRecorder | undefined;
+ private _videoRec: MediaRecorder | undefined;
@observable private _videoRef: HTMLVideoElement | null = null;
@observable _screenCapture = false;
@computed get recordingStart() {
@@ -136,7 +137,7 @@ export class ScreenshotBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
};
videoLoad = () => {
- const aspect = this._videoRef!.videoWidth / this._videoRef!.videoHeight;
+ const aspect = (this._videoRef?.videoWidth || 0) / (this._videoRef?.videoHeight || 1);
const nativeWidth = Doc.NativeWidth(this.layoutDoc);
const nativeHeight = Doc.NativeHeight(this.layoutDoc);
if (!nativeWidth || !nativeHeight) {
@@ -166,7 +167,7 @@ export class ScreenshotBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
}
specificContextMenu = (): void => {
- const subitems = [{ description: 'Screen Capture', event: this.toggleRecording, icon: 'expand-arrows-alt' as any }];
+ const subitems = [{ description: 'Screen Capture', event: this.toggleRecording, icon: 'expand-arrows-alt' as IconProp }];
ContextMenu.Instance.addItem({ description: 'Options...', subitems, icon: 'video' });
};
@@ -221,29 +222,29 @@ export class ScreenshotBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
Pause = () => this._screenCapture && this.toggleRecording();
toggleRecording = async () => {
- if (!this._screenCapture) {
+ if (!this._screenCapture && this._videoRef) {
this._audioRec = new MediaRecorder(await navigator.mediaDevices.getUserMedia({ audio: true }));
- const audChunks: any = [];
- this._audioRec.ondataavailable = (e: any) => audChunks.push(e.data);
+ const audChunks: Blob[] = [];
+ this._audioRec.ondataavailable = e => audChunks.push(e.data);
this._audioRec.onstop = async () => {
- const [{ result }] = await Networking.UploadFilesToServer(audChunks.map((file: any) => ({ file })));
+ const [{ result }] = await Networking.UploadFilesToServer(audChunks.map(file => ({ file })));
if (!(result instanceof Error)) {
this.dataDoc[this._props.fieldKey + '_audio'] = new AudioField(result.accessPaths.agnostic.client);
}
};
- this._videoRef!.srcObject = await (navigator.mediaDevices as any).getDisplayMedia({ video: true });
- this._videoRec = new MediaRecorder(this._videoRef!.srcObject);
- const vidChunks: any = [];
+ this._videoRef.srcObject = await navigator.mediaDevices.getDisplayMedia({ video: true });
+ this._videoRec = new MediaRecorder(this._videoRef.srcObject);
+ const vidChunks: Blob[] = [];
this._videoRec.onstart = () => {
if (this.dataDoc[this._props.fieldKey + '_trackScreen']) TrackMovements.Instance.start();
this.dataDoc[this._props.fieldKey + '_recordingStart'] = new DateField(new Date());
};
- this._videoRec.ondataavailable = (e: any) => vidChunks.push(e.data);
+ this._videoRec.ondataavailable = e => vidChunks.push(e.data);
this._videoRec.onstop = async () => {
const presentation = TrackMovements.Instance.yieldPresentation();
if (presentation?.movements) {
const presCopy = { ...presentation };
- presCopy.movements = presentation.movements.map(movement => ({ ...movement, doc: movement.doc[Id] })) as any;
+ presCopy.movements = presentation.movements.map(movement => ({ ...movement, doc: (movement.doc as Doc)[Id] }) as Movement);
this.dataDoc[this.fieldKey + '_presentation'] = JSON.stringify(presCopy);
}
TrackMovements.Instance.finish();
diff --git a/src/client/views/nodes/ScriptingBox.tsx b/src/client/views/nodes/ScriptingBox.tsx
index bc19d7ad1..8da422039 100644
--- a/src/client/views/nodes/ScriptingBox.tsx
+++ b/src/client/views/nodes/ScriptingBox.tsx
@@ -1,8 +1,8 @@
/* eslint-disable react/button-has-type */
-/* eslint-disable jsx-a11y/no-static-element-interactions */
import { action, computed, makeObservable, observable } from 'mobx';
import { observer } from 'mobx-react';
import * as React from 'react';
+import ResizeObserver from 'resize-observer-polyfill';
import { returnAlways, returnEmptyString } from '../../../ClientUtils';
import { Doc } from '../../../fields/Doc';
import { List } from '../../../fields/List';
@@ -10,21 +10,26 @@ import { listSpec } from '../../../fields/Schema';
import { ScriptField } from '../../../fields/ScriptField';
import { BoolCast, Cast, DocCast, NumCast, ScriptCast, StrCast } from '../../../fields/Types';
import { TraceMobx } from '../../../fields/util';
+import { DocumentType } from '../../documents/DocumentTypes';
+import { Docs } from '../../documents/Documents';
import { DragManager } from '../../util/DragManager';
import { ScriptManager } from '../../util/ScriptManager';
-import { CompileScript, ScriptParam } from '../../util/Scripting';
+import { CompileError, CompileScript, ScriptParam } from '../../util/Scripting';
import { ScriptingGlobals } from '../../util/ScriptingGlobals';
import { ContextMenu } from '../ContextMenu';
import { ViewBoxAnnotatableComponent } from '../DocComponent';
import { EditableView } from '../EditableView';
import { OverlayView } from '../OverlayView';
-import { FieldView, FieldViewProps } from './FieldView';
import { DocumentIconContainer } from './DocumentIcon';
+import { FieldView, FieldViewProps } from './FieldView';
import './ScriptingBox.scss';
-import { Docs } from '../../documents/Documents';
-import { DocumentType } from '../../documents/DocumentTypes';
+import * as ts from 'typescript';
+import { FieldType } from '../../../fields/ObjectField';
+
+// eslint-disable-next-line @typescript-eslint/no-var-requires
+const getCaretCoordinates = require('textarea-caret');
-const _global = (window /* browser */ || global) /* node */ as any;
+// eslint-disable-next-line @typescript-eslint/no-var-requires
const ReactTextareaAutocomplete = require('@webscopeio/react-textarea-autocomplete').default;
@observer
@@ -41,9 +46,9 @@ export class ScriptingBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
@observable private _function: boolean = false;
@observable private _spaced: boolean = false;
- @observable private _scriptKeys: any = ScriptingGlobals.getGlobals();
- @observable private _scriptingDescriptions: any = ScriptingGlobals.getDescriptions();
- @observable private _scriptingParams: any = ScriptingGlobals.getParameters();
+ @observable private _scriptKeys = ScriptingGlobals.getGlobals();
+ @observable private _scriptingDescriptions = ScriptingGlobals.getDescriptions();
+ @observable private _scriptingParams = ScriptingGlobals.getParameters();
@observable private _currWord: string = '';
@observable private _suggestions: string[] = [];
@@ -52,20 +57,20 @@ export class ScriptingBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
@observable private _suggestionBoxY: number = 0;
@observable private _lastChar: string = '';
- @observable private _suggestionRef: any = React.createRef();
- @observable private _scriptTextRef: any = React.createRef();
+ @observable private _suggestionRef = React.createRef<HTMLDivElement>();
+ @observable private _scriptTextRef = React.createRef<HTMLDivElement>();
- @observable private _selection: any = 0;
+ @observable private _selection = 0;
@observable private _paramSuggestion: boolean = false;
- @observable private _scriptSuggestedParams: any = '';
- @observable private _scriptParamsText: any = '';
+ @observable private _scriptSuggestedParams: JSX.Element | string = '';
+ @observable private _scriptParamsText = '';
constructor(props: FieldViewProps) {
super(props);
makeObservable(this);
if (!this.compileParams.length) {
- const params = ScriptCast(this.dataDoc[this._props.fieldKey])?.script.options.params as { [key: string]: any };
+ const params = ScriptCast(this.dataDoc[this._props.fieldKey])?.script.options.params as { [key: string]: string };
if (params) {
this.compileParams = Array.from(Object.keys(params))
.filter(p => !p.startsWith('_'))
@@ -106,26 +111,16 @@ export class ScriptingBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
this.dataDoc[this.fieldKey + '-params'] = new List<string>(value);
}
- getValue(result: any, descrip: boolean) {
- if (typeof result === 'object') {
- const text = descrip ? result[1] : result[2];
- return text !== undefined ? text : '';
- }
- return '';
- }
-
onClickScriptDisable = returnAlways;
@action
componentDidMount() {
this._props.setContentViewBox?.(this);
this.rawText = this.rawScript;
- const resizeObserver = new _global.ResizeObserver(
+ const resizeObserver = new ResizeObserver(
action(() => {
const area = document.querySelector('textarea');
if (area) {
- // eslint-disable-next-line global-require
- const getCaretCoordinates = require('textarea-caret');
const caret = getCaretCoordinates(area, this._selection);
this.resetSuggestionPos(caret);
}
@@ -135,12 +130,12 @@ export class ScriptingBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
}
@action
- resetSuggestionPos(caret: any) {
+ resetSuggestionPos(caret: { top: number; left: number; height: number }) {
if (!this._suggestionRef.current || !this._scriptTextRef.current) return;
const suggestionWidth = this._suggestionRef.current.offsetWidth;
const scriptWidth = this._scriptTextRef.current.offsetWidth;
const { top } = caret;
- const { x } = this.dataDoc;
+ const x = NumCast(this.layoutDoc.x);
let { left } = caret;
if (left + suggestionWidth > x + scriptWidth) {
const diff = left + suggestionWidth - (x + scriptWidth);
@@ -171,8 +166,8 @@ export class ScriptingBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
// displays error message
@action
- onError = (error: any) => {
- this._errorMessage = error?.message ? error.message : error?.map((entry: any) => entry.messageText).join(' ') || '';
+ onError = (errors: ts.Diagnostic[] | string) => {
+ this._errorMessage = typeof errors === 'string' ? errors : errors.map(entry => entry.toString()).join(' ') || '';
};
// checks if the script compiles using CompileScript method and inputting params
@@ -184,7 +179,7 @@ export class ScriptingBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
});
const result = !this.rawText.trim()
- ? ({ compiled: false, errors: undefined } as any)
+ ? ({ compiled: false, errors: [] } as CompileError)
: CompileScript(this.rawText, {
editable: true,
transformer: DocumentIconContainer.getTransformer(),
@@ -192,7 +187,7 @@ export class ScriptingBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
typecheck: false,
});
this.dataDoc[this.fieldKey] = result.compiled ? new ScriptField(result, undefined, this.rawText) : undefined;
- this.onError(result.compiled ? undefined : result.errors);
+ this.onError(result.compiled ? [] : result.errors);
return result.compiled;
};
@@ -200,7 +195,7 @@ export class ScriptingBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
@action
onRun = () => {
if (this.onCompile()) {
- const bindings: { [name: string]: any } = {};
+ const bindings: { [name: string]: unknown } = {};
this.paramsNames.forEach(key => {
bindings[key] = this.dataDoc[key];
});
@@ -294,8 +289,8 @@ export class ScriptingBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
// sets field of the param name to the selected value in drop down box
@action
- viewChanged = (e: React.ChangeEvent, name: string) => {
- const val = (e.target as any).selectedOptions[0].value;
+ viewChanged = (e: React.ChangeEvent<HTMLSelectElement>, name: string) => {
+ const val = e.target.selectedOptions[0].value;
this.dataDoc[name] = val[0] === 'S' ? val.substring(1) : val[0] === 'N' ? parseInt(val.substring(1)) : val.substring(1) === 'true';
};
@@ -309,7 +304,7 @@ export class ScriptingBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
// adds option to create a copy to the context menu
specificContextMenu = (): void => {
const existingOptions = ContextMenu.Instance.findByDescription('Options...');
- const options = existingOptions && 'subitems' in existingOptions ? existingOptions.subitems : [];
+ const options = existingOptions?.subitems ?? [];
options.push({ description: 'Create a Copy', event: this.onCopy, icon: 'copy' });
!existingOptions && ContextMenu.Instance.addItem({ description: 'Options...', subitems: options, icon: 'hand-point-right' });
};
@@ -381,7 +376,7 @@ export class ScriptingBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
const results = script.compiled && script.run();
if (results && results.success) {
this._errorMessage = '';
- this.dataDoc[parameter] = results.result;
+ this.dataDoc[parameter] = results.result as FieldType;
return true;
}
this._errorMessage = 'invalid document';
@@ -524,18 +519,17 @@ export class ScriptingBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
@action
suggestionPos = () => {
- // eslint-disable-next-line global-require
- const getCaretCoordinates = require('textarea-caret');
+ // eslint-disable-next-line @typescript-eslint/no-this-alias
const This = this;
document.querySelector('textarea')?.addEventListener('input', function () {
- const caret = getCaretCoordinates(this, this.selectionEnd);
- This._selection = this;
+ const caret = getCaretCoordinates(this, this.selectionEnd) as { top: number; left: number; height: number };
+ // This._selection = this;
This.resetSuggestionPos(caret);
});
};
@action
- keyHandler(e: any, pos: number) {
+ keyHandler(e: React.KeyboardEvent, pos: number) {
e.stopPropagation();
if (this._lastChar === 'Enter') {
this.rawText += ' ';
@@ -602,7 +596,7 @@ export class ScriptingBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
}
@action
- handlePosChange(number: any) {
+ handlePosChange(number: number) {
this._caretPos = number;
if (this._caretPos === 0) {
this.rawText = ' ' + this.rawText;
@@ -625,7 +619,7 @@ export class ScriptingBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
placeholder="write your script here"
onFocus={this.onFocus}
onBlur={() => this._overlayDisposer?.()}
- onChange={action((e: any) => {
+ onChange={action((e: React.ChangeEvent<HTMLSelectElement>) => {
this.rawText = e.target.value;
})}
value={this.rawText}
@@ -633,24 +627,24 @@ export class ScriptingBox extends ViewBoxAnnotatableComponent<FieldViewProps>()
loadingComponent={() => <span>Loading</span>}
trigger={{
' ': {
- dataProvider: (token: any) => this.handleToken(token),
- component: (blob: any) => this.renderFuncListElement(blob.entity),
- output: (item: any, trigger: any) => {
+ dataProvider: this.handleToken,
+ component: (blob: { entity: string }) => this.renderFuncListElement(blob.entity),
+ output: (item: string, trigger: string) => {
this._spaced = true;
return trigger + item.trim();
},
},
'.': {
- dataProvider: (token: any) => this.handleToken(token),
- component: (blob: any) => this.renderFuncListElement(blob.entity),
- output: (item: any, trigger: any) => {
+ dataProvider: this.handleToken,
+ component: (blob: { entity: string }) => this.renderFuncListElement(blob.entity),
+ output: (item: string, trigger: string) => {
this._spaced = true;
return trigger + item.trim();
},
},
}}
onKeyDown={(e: React.KeyboardEvent) => this.keyHandler(e, this._caretPos)}
- onCaretPositionChange={(number: any) => this.handlePosChange(number)}
+ onCaretPositionChange={this.handlePosChange}
/>
</div>
);
diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx
index 1f285b300..4933869a7 100644
--- a/src/client/views/nodes/VideoBox.tsx
+++ b/src/client/views/nodes/VideoBox.tsx
@@ -125,8 +125,8 @@ export class VideoBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
}
override PlayerTime = () => this.player?.currentTime;
- override Pause = (update: boolean = true) => {
- this.pause(update);
+ override Pause = () => {
+ this.pause(true);
!this._keepCurrentlyPlaying && this.removeCurrentlyPlaying();
};
@@ -157,7 +157,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
};
// plays video
- @action public Play = (update: boolean = true) => {
+ @action public Play = () => {
if (this._playRegionTimer) return;
this._playing = true;
@@ -172,8 +172,8 @@ export class VideoBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
}
try {
this._audioPlayer && this.player && (this._audioPlayer.currentTime = this.player?.currentTime);
- update && this.player && this.playFrom(start, undefined, true);
- update && this._audioPlayer?.play();
+ this.player && this.playFrom(start, undefined, true);
+ this._audioPlayer?.play();
} catch (e) {
console.log('Video Play Exception:', e);
}
@@ -384,7 +384,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
getVideoThumbnails = () => {
if (this.dataDoc[this.fieldKey + '_thumbnails'] !== undefined) return;
this.dataDoc[this.fieldKey + '_thumbnails'] = new List<string>();
- const thumbnailPromises: Promise<any>[] = [];
+ const thumbnailPromises: Promise<string>[] = [];
const video = document.createElement('video');
video.onloadedmetadata = () => {
@@ -467,7 +467,7 @@ export class VideoBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
runInAction(() => {
this._screenCapture = !this._screenCapture;
});
- this._videoRef!.srcObject = !this._screenCapture ? null : await (navigator.mediaDevices).getDisplayMedia({ video: true });
+ this._videoRef!.srcObject = !this._screenCapture ? null : await navigator.mediaDevices.getDisplayMedia({ video: true });
},
icon: 'expand-arrows-alt',
});
@@ -557,9 +557,9 @@ export class VideoBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
style={this._fullScreen ? this.fullScreenSize() : this.isCropped ? { width: 'max-content', height: 'max-content', transform: `scale(${1 / NumCast(this.layoutDoc._freeform_scale)})`, transformOrigin: 'top left' } : {}}
onCanPlay={this.videoLoad}
controls={false}
- onPlay={() => this.Play()}
+ onPlay={this.Play}
onSeeked={this.updateTimecode}
- onPause={() => this.Pause()}
+ onPause={this.Pause}
onClick={this._fullScreen ? () => (this.playing() ? this.Pause() : this.Play()) : e => e.preventDefault()}>
<source src={field.url.href} type="video/mp4" />
Not supported.
diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx
index be7e0f483..1fd73c226 100644
--- a/src/client/views/nodes/WebBox.tsx
+++ b/src/client/views/nodes/WebBox.tsx
@@ -1,4 +1,5 @@
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import { Property } from 'csstype';
import { htmlToText } from 'html-to-text';
import { action, computed, IReactionDisposer, makeObservable, observable, ObservableMap, reaction, runInAction } from 'mobx';
import { observer } from 'mobx-react';
@@ -21,7 +22,7 @@ import { DocumentType } from '../../documents/DocumentTypes';
import { DocUtils } from '../../documents/DocUtils';
import { ScriptingGlobals } from '../../util/ScriptingGlobals';
import { SnappingManager } from '../../util/SnappingManager';
-import { undoBatch, UndoManager } from '../../util/UndoManager';
+import { undoable, UndoManager } from '../../util/UndoManager';
import { MarqueeOptionsMenu } from '../collections/collectionFreeForm';
import { CollectionFreeFormView } from '../collections/collectionFreeForm/CollectionFreeFormView';
import { ContextMenu } from '../ContextMenu';
@@ -83,7 +84,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
this._marqueeing = val;
}
@observable private _iframe: HTMLIFrameElement | null = null;
- @observable private _savedAnnotations = new ObservableMap<number, (HTMLDivElement& { marqueeing?: boolean})[]>();
+ @observable private _savedAnnotations = new ObservableMap<number, (HTMLDivElement & { marqueeing?: boolean })[]>();
@observable private _scrollHeight = NumCast(this.layoutDoc.scrollHeight);
@computed get _url() {
return this.webField?.toString() || '';
@@ -121,11 +122,12 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
});
}
try {
+ const contentWindow = this._iframe?.contentWindow;
if (clear) {
- this._iframe?.contentWindow?.getSelection()?.empty();
+ contentWindow?.getSelection()?.empty();
}
- if (searchString) {
- (this._iframe?.contentWindow as any)?.find(searchString, false, bwd, true);
+ if (searchString && contentWindow && 'find' in contentWindow) {
+ (contentWindow.find as (str: string, caseSens?: boolean, backward?: boolean, wrapAround?: boolean) => void)(searchString, false, bwd, true);
}
} catch (e) {
console.log('WebBox search error', e);
@@ -142,7 +144,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
}
};
- updateThumb = async () => {
+ updateIcon = async () => {
if (!this._iframe) return;
const scrollTop = NumCast(this.layoutDoc._layout_scrollTop);
const nativeWidth = NumCast(this.layoutDoc.nativeWidth);
@@ -154,7 +156,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
this.layoutDoc.thumb = undefined;
this.Document.thumbLockout = true; // lock to prevent multiple thumb updates.
CreateImage(this._webUrl.endsWith('/') ? this._webUrl.substring(0, this._webUrl.length - 1) : this._webUrl, this._iframe.contentDocument?.styleSheets ?? [], htmlString, nativeWidth, nativeHeight, scrollTop)
- .then((dataUrl: any) => {
+ .then((dataUrl: string) => {
if (dataUrl.includes('<!DOCTYPE')) {
console.log('BAD DATA IN THUMB CREATION');
return;
@@ -172,7 +174,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
)
);
})
- .catch((error: any) => {
+ .catch((error: object) => {
console.error('oops, something went wrong!', error);
});
};
@@ -359,8 +361,8 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
return anchor;
};
- _textAnnotationCreator: (() => ObservableMap<number, (HTMLDivElement & { marqueeing?: boolean})[]>) | undefined;
- savedAnnotationsCreator: () => ObservableMap<number, (HTMLDivElement & { marqueeing?: boolean})[]> = () => this._textAnnotationCreator?.() || this._savedAnnotations;
+ _textAnnotationCreator: (() => ObservableMap<number, (HTMLDivElement & { marqueeing?: boolean })[]>) | undefined;
+ savedAnnotationsCreator: () => ObservableMap<number, (HTMLDivElement & { marqueeing?: boolean })[]> = () => this._textAnnotationCreator?.() || this._savedAnnotations;
@action
iframeMove = (e: PointerEvent) => {
@@ -424,11 +426,11 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
sel.empty(); // Chrome
else if (sel?.removeAllRanges) sel.removeAllRanges(); // Firefox
// bcz: NEED TO unrotate e.clientX and e.clientY
- const word = getWordAtPoint(e.target, e.clientX, e.clientY);
+ const target = e.target as HTMLElement;
+ const word = target && getWordAtPoint(target, e.clientX, e.clientY);
this._setPreviewCursor?.(e.clientX, e.clientY, false, true, this.Document);
MarqueeAnnotator.clearAnnotations(this._savedAnnotations);
- const target = e.target as HTMLElement;
if (!word && !target?.className?.includes('rangeslider') && !target?.onclick && !target?.parentElement?.onclick) {
if (e.button !== 2) this.marqueeing = [e.clientX, e.clientY];
e.preventDefault();
@@ -468,8 +470,8 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
.inverse()
.transformPoint(e.clientX, e.clientY - NumCast(this.layoutDoc.layout_scrollTop));
MarqueeAnnotator.clearAnnotations(this._savedAnnotations);
- const word = getWordAtPoint(e.target, e.clientX, e.clientY);
const target = e.target as HTMLElement;
+ const word = target && getWordAtPoint(target, e.clientX, e.clientY);
if (!word && !target?.className?.includes('rangeslider') && !target?.onclick && !target?.parentElement?.onclick) {
this.marqueeing = theclick;
this._marqueeref.current?.onInitiateSelection(this.marqueeing);
@@ -488,7 +490,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
}
return undefined;
}
- addWebStyleSheetRule(sheet: CSSStyleSheet | null | undefined, selector: string, css: {[key:string]: string}, selectorPrefix = '.') {
+ addWebStyleSheetRule(sheet: CSSStyleSheet | null | undefined, selector: string, css: { [key: string]: string }, selectorPrefix = '.') {
const propText =
typeof css === 'string'
? css
@@ -498,7 +500,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
return sheet?.insertRule(selectorPrefix + selector + '{' + propText + '}', sheet.cssRules.length);
}
- _iframetimeout: NodeJS.Timeout|undefined = undefined;
+ _iframetimeout: NodeJS.Timeout | undefined = undefined;
@observable _warning = 0;
@action
iframeLoaded = () => {
@@ -520,7 +522,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
if (requrlraw !== this._url.toString()) {
if (requrlraw.match(/q=.*&/)?.length && this._url.toString().match(/q=.*&/)?.length) {
const matches = requrlraw.match(/[^a-zA-z]q=[^&]*/g);
- const newsearch = matches?.lastElement() || "";
+ const newsearch = matches?.lastElement() || '';
if (matches) {
requrlraw = requrlraw.substring(0, requrlraw.indexOf(newsearch));
for (let i = 1; i < Array.from(matches)?.length; i++) {
@@ -567,12 +569,12 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
);
iframeContent.addEventListener(
'click',
- undoBatch(
+ undoable(
action((e: MouseEvent) => {
let eleHref = '';
for (let ele = e.target as HTMLElement | Element | null; ele; ele = ele.parentElement) {
if (ele instanceof HTMLAnchorElement) {
- eleHref = (typeof ele.href === 'string' ? ele.href : eleHref) || (ele.parentElement && ("href" in ele.parentElement) ? ele.parentElement.href as string: eleHref);
+ eleHref = (typeof ele.href === 'string' ? ele.href : eleHref) || (ele.parentElement && 'href' in ele.parentElement ? (ele.parentElement.href as string) : eleHref);
}
}
const origin = this.webField?.origin;
@@ -588,7 +590,8 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
this._outerRef.current.scrollLeft = 0;
}
}
- })
+ }),
+ 'follow web link'
)
);
iframe.contentDocument.addEventListener('wheel', this.iframeWheel, { passive: false });
@@ -792,7 +795,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
},
icon: 'snowflake',
});
- funcs.push({ description: 'Create Thumbnail', event: () => this.updateThumb(), icon: 'portrait' });
+ !Doc.noviceMode && funcs.push({ description: 'Update Icon', event: () => this.updateIcon(), icon: 'portrait' });
cm.addItem({ description: 'Options...', subitems: funcs, icon: 'asterisk' });
}
};
@@ -1085,7 +1088,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
@computed get webpage() {
TraceMobx();
const previewScale = this._previewNativeWidth ? 1 - this.sidebarWidth() / this._previewNativeWidth : 1;
- const pointerEvents = this.layoutDoc._lockedPosition ? 'none' : (this._props.pointerEvents?.() as "none" | "all" | "visiblePainted" | undefined)
+ const pointerEvents = this.layoutDoc._lockedPosition ? 'none' : (this._props.pointerEvents?.() as Property.PointerEvents | undefined);
const scale = previewScale * (this._props.NativeDimScaling?.() || 1);
return (
<div
@@ -1170,7 +1173,7 @@ export class WebBox extends ViewBoxAnnotatableComponent<FieldViewProps>() {
render() {
TraceMobx();
const previewScale = this._previewNativeWidth ? 1 - this.sidebarWidth() / this._previewNativeWidth : 1;
- const pointerEvents = this.layoutDoc._lockedPosition ? 'none' : (this._props.pointerEvents?.() as 'none' | 'all' | 'visiblePainted' | undefined);
+ const pointerEvents = this.layoutDoc._lockedPosition ? 'none' : (this._props.pointerEvents?.() as Property.PointerEvents);
const scale = previewScale * (this._props.NativeDimScaling?.() || 1);
return (
<div
diff --git a/src/client/views/nodes/WebBoxRenderer.js b/src/client/views/nodes/WebBoxRenderer.js
index 6fb8f4957..b727107a9 100644
--- a/src/client/views/nodes/WebBoxRenderer.js
+++ b/src/client/views/nodes/WebBoxRenderer.js
@@ -4,8 +4,6 @@
* @param {StyleSheetList} styleSheets
*/
const ForeignHtmlRenderer = function (styleSheets) {
- const self = this;
-
/**
*
* @param {String} binStr
@@ -252,15 +250,14 @@ const ForeignHtmlRenderer = function (styleSheets) {
*/
this.renderToImage = (webUrl, html, width, height, scroll, xoff) =>
new Promise(resolve => {
- const img = new Image();
- img.onload = function () {
- console.log(`IMAGE SVG created: ${webUrl}`);
- resolve(img);
- };
console.log(`BUILDING SVG for: ${webUrl}`);
buildSvgDataUri(webUrl, html, width, height, scroll, xoff).then(uri => {
+ const img = new Image();
img.src = uri;
- return img;
+ img.onload = () => {
+ console.log(`IMAGE SVG created: ${webUrl}`);
+ resolve(img);
+ };
});
});
@@ -272,7 +269,7 @@ const ForeignHtmlRenderer = function (styleSheets) {
* @return {Promise<Image>}
*/
this.renderToCanvas = (webUrl, html, width, height, scroll, xoff, oversample) =>
- self.renderToImage(webUrl, html, width, height, scroll, xoff).then(img => {
+ this.renderToImage(webUrl, html, width, height, scroll, xoff).then(img => {
const canvas = document.createElement('canvas');
canvas.width = img.width * oversample;
canvas.height = img.height * oversample;
@@ -290,8 +287,7 @@ const ForeignHtmlRenderer = function (styleSheets) {
* @return {Promise<String>}
*/
this.renderToBase64Png = (webUrl, html, width, height, scroll, xoff, oversample) =>
- self
- .renderToCanvas(webUrl, html, width, height, scroll, xoff, oversample) //
+ this.renderToCanvas(webUrl, html, width, height, scroll, xoff, oversample) //
.then(canvas => canvas.toDataURL('image/png'));
};
diff --git a/src/client/views/nodes/audio/AudioWaveform.tsx b/src/client/views/nodes/audio/AudioWaveform.tsx
index 2d1d3d7db..297deb575 100644
--- a/src/client/views/nodes/audio/AudioWaveform.tsx
+++ b/src/client/views/nodes/audio/AudioWaveform.tsx
@@ -39,7 +39,7 @@ export class AudioWaveform extends ObservableReactComponent<AudioWaveformProps>
public static NUMBER_OF_BUCKETS = 100; // number of buckets data is divided into to draw waveform lines
_disposer: IReactionDisposer | undefined;
- constructor(props: any) {
+ constructor(props: AudioWaveformProps) {
super(props);
makeObservable(this);
}
diff --git a/src/client/views/nodes/formattedText/DashDocCommentView.tsx b/src/client/views/nodes/formattedText/DashDocCommentView.tsx
index 3ec49fa27..0304ddc86 100644
--- a/src/client/views/nodes/formattedText/DashDocCommentView.tsx
+++ b/src/client/views/nodes/formattedText/DashDocCommentView.tsx
@@ -5,18 +5,20 @@ import { IReactionDisposer, computed, reaction } from 'mobx';
import { Doc } from '../../../../fields/Doc';
import { DocServer } from '../../../DocServer';
import { NumCast } from '../../../../fields/Types';
+import { Node } from 'prosemirror-model';
+import { EditorView } from 'prosemirror-view';
interface IDashDocCommentViewInternal {
docId: string;
- view: any;
- getPos: any;
+ view: EditorView;
+ getPos: () => number;
setHeight: (height: number) => void;
}
export class DashDocCommentViewInternal extends React.Component<IDashDocCommentViewInternal> {
_reactionDisposer: IReactionDisposer | undefined;
- constructor(props: any) {
+ constructor(props: IDashDocCommentViewInternal) {
super(props);
this.onPointerLeaveCollapsed = this.onPointerLeaveCollapsed.bind(this);
this.onPointerEnterCollapsed = this.onPointerEnterCollapsed.bind(this);
@@ -43,19 +45,19 @@ export class DashDocCommentViewInternal extends React.Component<IDashDocCommentV
return DocServer.GetRefField(this.props.docId);
}
- onPointerLeaveCollapsed = (e: any) => {
+ onPointerLeaveCollapsed = (e: React.PointerEvent) => {
this._dashDoc.then(async dashDoc => dashDoc instanceof Doc && Doc.linkFollowUnhighlight());
e.preventDefault();
e.stopPropagation();
};
- onPointerEnterCollapsed = (e: any) => {
+ onPointerEnterCollapsed = (e: React.PointerEvent) => {
this._dashDoc.then(async dashDoc => dashDoc instanceof Doc && Doc.linkFollowHighlight(dashDoc, false));
e.preventDefault();
e.stopPropagation();
};
- onPointerUpCollapsed = (e: any) => {
+ onPointerUpCollapsed = (e: React.PointerEvent) => {
const target = this.targetNode();
if (target) {
@@ -65,7 +67,7 @@ export class DashDocCommentViewInternal extends React.Component<IDashDocCommentV
setTimeout(() => {
expand && this._dashDoc.then(async dashDoc => dashDoc instanceof Doc && Doc.linkFollowHighlight(dashDoc));
try {
- this.props.view.dispatch(this.props.view.state.tr.setSelection(TextSelection.create(this.props.view.state.tr.doc, this.props.getPos() + (expand ? 2 : 1))));
+ this.props.view.dispatch(this.props.view.state.tr.setSelection(TextSelection.create(this.props.view.state.tr.doc, (this.props.getPos() ?? 0) + (expand ? 2 : 1))));
} catch (err) {
/* empty */
}
@@ -74,7 +76,7 @@ export class DashDocCommentViewInternal extends React.Component<IDashDocCommentV
e.stopPropagation();
};
- onPointerDownCollapsed = (e: any) => {
+ onPointerDownCollapsed = (e: React.PointerEvent) => {
e.stopPropagation();
};
@@ -84,7 +86,7 @@ export class DashDocCommentViewInternal extends React.Component<IDashDocCommentV
for (let i = this.props.getPos() + 1; i < state.doc.content.size; i++) {
const m = state.doc.nodeAt(i);
if (m && m.type === state.schema.nodes.dashDoc && m.attrs.docId === this.props.docId) {
- return { node: m, pos: i, hidden: m.attrs.hidden } as { node: any; pos: number; hidden: boolean };
+ return { node: m, pos: i, hidden: m.attrs.hidden } as { node: Node; pos: number; hidden: boolean };
}
}
@@ -119,10 +121,10 @@ export class DashDocCommentViewInternal extends React.Component<IDashDocCommentV
// the comment can be toggled on/off with the '<-' text anchor.
export class DashDocCommentView {
dom: HTMLDivElement; // container for label and value
- root: any;
- node: any;
+ root: ReactDOM.Root;
+ node: Node;
- constructor(node: any, view: any, getPos: any) {
+ constructor(node: Node, view: EditorView, getPos: () => number | undefined) {
this.node = node;
this.dom = document.createElement('div');
this.dom.style.width = node.attrs.width;
@@ -130,22 +132,22 @@ export class DashDocCommentView {
this.dom.style.fontWeight = 'bold';
this.dom.style.position = 'relative';
this.dom.style.display = 'inline-block';
- this.dom.onkeypress = function (e: any) {
+ this.dom.onkeypress = function (e) {
e.stopPropagation();
};
- this.dom.onkeydown = function (e: any) {
+ this.dom.onkeydown = function (e) {
e.stopPropagation();
};
- this.dom.onkeyup = function (e: any) {
+ this.dom.onkeyup = function (e) {
e.stopPropagation();
};
- this.dom.onmousedown = function (e: any) {
+ this.dom.onmousedown = function (e) {
e.stopPropagation();
};
+ const getPosition = () => getPos() ?? 0;
this.root = ReactDOM.createRoot(this.dom);
- this.root.render(<DashDocCommentViewInternal view={view} getPos={getPos} setHeight={this.setHeight} docId={node.attrs.docId} />);
- (this as any).dom = this.dom;
+ this.root.render(<DashDocCommentViewInternal view={view} getPos={getPosition} setHeight={this.setHeight} docId={node.attrs.docId} />);
}
setHeight = (hgt: number) => {
diff --git a/src/client/views/nodes/formattedText/DashDocView.tsx b/src/client/views/nodes/formattedText/DashDocView.tsx
index 93371685d..e7f2cdba8 100644
--- a/src/client/views/nodes/formattedText/DashDocView.tsx
+++ b/src/client/views/nodes/formattedText/DashDocView.tsx
@@ -1,4 +1,3 @@
-/* eslint-disable jsx-a11y/no-static-element-interactions */
import { action, computed, IReactionDisposer, makeObservable, observable, reaction } from 'mobx';
import { observer } from 'mobx-react';
import { NodeSelection } from 'prosemirror-state';
@@ -16,6 +15,8 @@ import { ObservableReactComponent } from '../../ObservableReactComponent';
import { DocumentView } from '../DocumentView';
import { FocusViewOptions } from '../FocusViewOptions';
import { FormattedTextBox } from './FormattedTextBox';
+import { EditorView } from 'prosemirror-view';
+import { Node } from 'prosemirror-model';
const horizPadding = 3; // horizontal padding to container to allow cursor to show up on either side.
interface IDashDocViewInternal {
@@ -26,9 +27,9 @@ interface IDashDocViewInternal {
height: string;
hidden: boolean;
fieldKey: string;
- view: any;
- node: any;
- getPos: any;
+ view: EditorView;
+ node: Node;
+ getPos: () => number;
}
@observer
@@ -109,7 +110,7 @@ export class DashDocViewInternal extends ObservableReactComponent<IDashDocViewIn
};
outerFocus = (target: Doc, options: FocusViewOptions) => this._textBox.focus(target, options); // ideally, this would scroll to show the focus target
- onKeyDown = (e: any) => {
+ onKeyDown = (e: React.KeyboardEvent) => {
e.stopPropagation();
if (e.key === 'Tab' || e.key === 'Enter') {
e.preventDefault();
@@ -176,29 +177,31 @@ export class DashDocViewInternal extends ObservableReactComponent<IDashDocViewIn
export class DashDocView {
dom: HTMLSpanElement; // container for label and value
- root: any;
+ root: ReactDOM.Root;
- constructor(node: any, view: any, getPos: any, tbox: FormattedTextBox) {
+ constructor(node: Node, view: EditorView, getPos: () => number | undefined, tbox: FormattedTextBox) {
this.dom = document.createElement('span');
this.dom.style.position = 'relative';
this.dom.style.textIndent = '0';
this.dom.style.width = (+node.attrs.width.toString().replace('px', '') + horizPadding).toString();
this.dom.style.height = node.attrs.height;
this.dom.style.display = node.attrs.hidden ? 'none' : 'inline-block';
- (this.dom.style as any).float = node.attrs.float;
- this.dom.onkeypress = function (e: any) {
+ this.dom.style.float = node.attrs.float;
+ this.dom.onkeypress = function (e: KeyboardEvent) {
e.stopPropagation();
};
- this.dom.onkeydown = function (e: any) {
+ this.dom.onkeydown = function (e: KeyboardEvent) {
e.stopPropagation();
};
- this.dom.onkeyup = function (e: any) {
+ this.dom.onkeyup = function (e: KeyboardEvent) {
e.stopPropagation();
};
- this.dom.onmousedown = function (e: any) {
+ this.dom.onmousedown = function (e: MouseEvent) {
e.stopPropagation();
};
+ const getPosition = () => getPos() ?? 0;
+
this.root = ReactDOM.createRoot(this.dom);
this.root.render(
<DashDocViewInternal
@@ -211,7 +214,7 @@ export class DashDocView {
tbox={tbox}
view={view}
node={node}
- getPos={getPos}
+ getPos={getPosition}
/>
);
}
diff --git a/src/client/views/nodes/formattedText/DashFieldView.tsx b/src/client/views/nodes/formattedText/DashFieldView.tsx
index 9903d0e8a..f0313fba4 100644
--- a/src/client/views/nodes/formattedText/DashFieldView.tsx
+++ b/src/client/views/nodes/formattedText/DashFieldView.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/control-has-associated-label */
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { Tooltip } from '@mui/material';
import { action, computed, IReactionDisposer, makeObservable, observable, reaction, runInAction } from 'mobx';
@@ -26,6 +23,8 @@ import { ObservableReactComponent } from '../../ObservableReactComponent';
import { OpenWhere } from '../OpenWhere';
import './DashFieldView.scss';
import { FormattedTextBox } from './FormattedTextBox';
+import { Node } from 'prosemirror-model';
+import { EditorView } from 'prosemirror-view';
@observer
export class DashFieldViewMenu extends AntimodeMenu<AntimodeMenuProps> {
@@ -34,7 +33,7 @@ export class DashFieldViewMenu extends AntimodeMenu<AntimodeMenuProps> {
static createFieldView: (e: React.MouseEvent) => void = emptyFunction;
static toggleFieldHide: () => void = emptyFunction;
static toggleValueHide: () => void = emptyFunction;
- constructor(props: any) {
+ constructor(props: AntimodeMenuProps) {
super(props);
DashFieldViewMenu.Instance = this;
}
@@ -100,8 +99,8 @@ interface IDashFieldViewInternal {
height: number;
editable: boolean;
nodeSelected: () => boolean;
- node: any;
- getPos: any;
+ node: Node;
+ getPos: () => number;
unclickable: () => boolean;
}
@@ -274,7 +273,9 @@ export class DashFieldViewInternal extends ObservableReactComponent<IDashFieldVi
<select className="dashFieldView-select" tabIndex={-1} defaultValue={this._dashDoc && Field.toKeyValueString(this._dashDoc, this._fieldKey)} onChange={this.selectVal}>
<option value="-unset-">-unset-</option>
{this.values.map(val => (
- <option value={val.value}>{val.label}</option>
+ <option key={val.value} value={val.value}>
+ {val.label}
+ </option>
))}
</select>
)}
@@ -284,16 +285,17 @@ export class DashFieldViewInternal extends ObservableReactComponent<IDashFieldVi
}
export class DashFieldView {
dom: HTMLDivElement; // container for label and value
- root: any;
- node: any;
+ root: ReactDOM.Root;
+ node: Node;
tbox: FormattedTextBox;
- getpos: any;
+ getpos: () => number | undefined;
@observable _nodeSelected = false;
NodeSelected = () => this._nodeSelected;
- unclickable = () => !this.tbox._props.rootSelected?.() && this.node.marks.some((m: any) => m.type === this.tbox.EditorView?.state.schema.marks.linkAnchor && m.attrs.noPreview);
- constructor(node: any, view: any, getPos: any, tbox: FormattedTextBox) {
+ unclickable = () => !this.tbox._props.rootSelected?.() && this.node.marks.some(m => m.type === this.tbox.EditorView?.state.schema.marks.linkAnchor && m.attrs.noPreview);
+ constructor(node: Node, view: EditorView, getPos: () => number | undefined, tbox: FormattedTextBox) {
makeObservable(this);
+ const getPosition = () => getPos() ?? 0;
this.node = node;
this.tbox = tbox;
this.getpos = getPos;
@@ -312,7 +314,7 @@ export class DashFieldView {
const editor = tbox.EditorView;
if (editor) {
const { state } = editor;
- for (let i = this.getpos() + 1; i < state.doc.content.size; i++) {
+ for (let i = getPosition() + 1; i < state.doc.content.size; i++) {
if (state.doc.nodeAt(i)?.type.name === state.schema.nodes.dashField.name) {
editor.dispatch(state.tr.setSelection(new NodeSelection(state.doc.resolve(i))));
return;
@@ -321,10 +323,10 @@ export class DashFieldView {
}
}
};
- this.dom.onkeyup = function (e: any) {
+ this.dom.onkeyup = function (e: KeyboardEvent) {
e.stopPropagation();
};
- this.dom.onmousedown = function (e: any) {
+ this.dom.onmousedown = function (e: MouseEvent) {
e.stopPropagation();
};
@@ -333,7 +335,7 @@ export class DashFieldView {
<DashFieldViewInternal
node={node}
unclickable={this.unclickable}
- getPos={getPos}
+ getPos={getPosition}
fieldKey={node.attrs.fieldKey}
docId={node.attrs.docId}
width={node.attrs.width}
diff --git a/src/client/views/nodes/formattedText/EquationEditor.tsx b/src/client/views/nodes/formattedText/EquationEditor.tsx
index d9b1a2cf8..8bb4a0a26 100644
--- a/src/client/views/nodes/formattedText/EquationEditor.tsx
+++ b/src/client/views/nodes/formattedText/EquationEditor.tsx
@@ -3,15 +3,12 @@ import React, { Component, createRef } from 'react';
// Import JQuery, required for the functioning of the equation editor
import $ from 'jquery';
-
import './EquationEditor.scss';
-// @ts-ignore
-window.jQuery = $;
-
-// @ts-ignore
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
+(window as any).jQuery = $;
require('mathquill/build/mathquill');
-
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
(window as any).MathQuill = (window as any).MathQuill.getInterface(1);
type EquationEditorProps = {
@@ -36,17 +33,18 @@ type EquationEditorProps = {
* @extends {Component<EquationEditorProps>}
*/
class EquationEditor extends Component<EquationEditorProps> {
- element: any;
+ element: React.RefObject<HTMLSpanElement>;
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
mathField: any;
ignoreEditEvents: number;
// Element needs to be in the class format and thus requires a constructor. The steps that are run
// in the constructor is to make sure that React can succesfully communicate with the equation
// editor.
- constructor(props: any) {
+ constructor(props: EquationEditorProps) {
super(props);
- this.element = createRef();
+ this.element = createRef<HTMLSpanElement>();
this.mathField = null;
// MathJax apparently fire 2 edit events on startup.
@@ -74,6 +72,7 @@ class EquationEditor extends Component<EquationEditorProps> {
autoOperatorNames,
};
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
this.mathField = (window as any).MathQuill.MathField(this.element.current, config);
this.mathField.latex(value || '');
}
diff --git a/src/client/views/nodes/formattedText/EquationView.tsx b/src/client/views/nodes/formattedText/EquationView.tsx
index 5167c8f2a..4d0e9efee 100644
--- a/src/client/views/nodes/formattedText/EquationView.tsx
+++ b/src/client/views/nodes/formattedText/EquationView.tsx
@@ -1,15 +1,16 @@
-/* eslint-disable jsx-a11y/no-static-element-interactions */
import { IReactionDisposer } from 'mobx';
import { observer } from 'mobx-react';
+import { Node } from 'prosemirror-model';
import { TextSelection } from 'prosemirror-state';
+import { EditorView } from 'prosemirror-view';
import * as React from 'react';
import * as ReactDOM from 'react-dom/client';
import { Doc } from '../../../../fields/Doc';
+import { DocData } from '../../../../fields/DocSymbols';
import { StrCast } from '../../../../fields/Types';
import './DashFieldView.scss';
import EquationEditor from './EquationEditor';
import { FormattedTextBox } from './FormattedTextBox';
-import { DocData } from '../../../../fields/DocSymbols';
interface IEquationViewInternal {
fieldKey: string;
@@ -27,7 +28,7 @@ export class EquationViewInternal extends React.Component<IEquationViewInternal>
_fieldKey: string;
_ref: React.RefObject<EquationEditor> = React.createRef();
- constructor(props: any) {
+ constructor(props: IEquationViewInternal) {
super(props);
this._fieldKey = props.fieldKey;
this._textBoxDoc = props.tbox.Document;
@@ -63,7 +64,7 @@ export class EquationViewInternal extends React.Component<IEquationViewInternal>
<EquationEditor
ref={this._ref}
value={StrCast(this._textBoxDoc[DocData][this._fieldKey])}
- onChange={(str: any) => {
+ onChange={str => {
this._textBoxDoc[DocData][this._fieldKey] = str;
}}
autoCommands="pi theta sqrt sum prod alpha beta gamma rho"
@@ -77,25 +78,27 @@ export class EquationViewInternal extends React.Component<IEquationViewInternal>
export class EquationView {
dom: HTMLDivElement; // container for label and value
- root: any;
+ root: ReactDOM.Root;
tbox: FormattedTextBox;
- view: any;
- constructor(node: any, view: any, getPos: any, tbox: FormattedTextBox) {
+ view: EditorView;
+ _editor: EquationEditor | undefined;
+ getPos: () => number;
+ constructor(node: Node, view: EditorView, getPos: () => number, tbox: FormattedTextBox) {
this.tbox = tbox;
this.view = view;
+ this.getPos = getPos;
this.dom = document.createElement('div');
this.dom.style.width = node.attrs.width;
this.dom.style.height = node.attrs.height;
this.dom.style.position = 'relative';
this.dom.style.display = 'inline-block';
- this.dom.onmousedown = function (e: any) {
+ this.dom.onmousedown = (e: MouseEvent) => {
e.stopPropagation();
};
this.root = ReactDOM.createRoot(this.dom);
this.root.render(<EquationViewInternal fieldKey={node.attrs.fieldKey} width={node.attrs.width} height={node.attrs.height} getPos={getPos} setEditor={this.setEditor} tbox={tbox} />);
}
- _editor: EquationEditor | undefined;
setEditor = (editor?: EquationEditor) => {
this._editor = editor;
};
@@ -106,6 +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.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 39e237986..c8b25e184 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBox.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBox.tsx
@@ -96,7 +96,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
private _sidebarTagRef = React.createRef<React.Component>();
private _ref: React.RefObject<HTMLDivElement> = React.createRef();
private _scrollRef: HTMLDivElement | null = null;
- private _editorView: Opt<EditorView & { TextView?: FormattedTextBox|undefined}>;
+ private _editorView: Opt<EditorView & { TextView?: FormattedTextBox | undefined }>;
public _applyingChange: string = '';
private _inDrop = false;
private _finishingLink = false;
@@ -113,7 +113,9 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
private _forceUncollapse = true; // if the cursor doesn't move between clicks, then the selection will disappear for some reason. This flags the 2nd click as happening on a selection which allows bullet points to toggle
private _break = true;
public ProseRef?: HTMLDivElement;
- set _recordingDictation(value) { !this.dataDoc[`${this.fieldKey}_recordingSource`] && (this.dataDoc.mediaState = value ? mediaState.Recording : undefined); }
+ set _recordingDictation(value) {
+ !this.dataDoc[`${this.fieldKey}_recordingSource`] && (this.dataDoc.mediaState = value ? mediaState.Recording : undefined);
+ }
@computed get _recordingDictation() { return this.dataDoc?.mediaState === mediaState.Recording; } // prettier-ignore
@computed get allSidebarDocs() { return DocListCast(this.dataDoc[this.SidebarKey]); } // prettier-ignore
@computed get noSidebar() { return this.DocumentView?.()._props.hideDecorationTitle || this._props.noSidebar || this.Document._layout_noSidebar; } // prettier-ignore
@@ -128,20 +130,26 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
@computed get config() {
this._keymap = buildKeymap(schema, this._props);
this._rules = new RichTextRules(this.Document, this);
- return { schema,
- plugins: [
- inputRules(this._rules.inpRules),
- this.richTextMenuPlugin(),
- history(),
- keymap(this._keymap),
- keymap(baseKeymap),
- new Plugin({ props: { attributes: { class: 'ProseMirror-example-setup-style' } } }),
- new Plugin({ view: () => new FormattedTextBoxComment() }),
- ] };
+ return {
+ schema,
+ plugins: [
+ inputRules(this._rules.inpRules),
+ this.richTextMenuPlugin(),
+ history(),
+ keymap(this._keymap),
+ keymap(baseKeymap),
+ new Plugin({ props: { attributes: { class: 'ProseMirror-example-setup-style' } } }),
+ new Plugin({ view: () => new FormattedTextBoxComment() }),
+ ],
+ };
}
- public get EditorView() { return this._editorView; }
- public get SidebarKey() { return this.fieldKey + '_sidebar'; }
+ public get EditorView() {
+ return this._editorView;
+ }
+ public get SidebarKey() {
+ return this.fieldKey + '_sidebar';
+ }
public makeAIFlashcards: () => void = unimplementedFunction;
public addToCollection: ((doc: Doc | Doc[], annotationKey?: string | undefined) => boolean) | undefined;
@@ -777,7 +785,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
specificContextMenu = (e: React.MouseEvent): void => {
const cm = ContextMenu.Instance;
- let target:Element|HTMLElement|null = e.target as HTMLElement; // hrefs are stored on the database of the <a> node that wraps the hyerlink <span>
+ let target: Element | HTMLElement | null = e.target as HTMLElement; // hrefs are stored on the database of the <a> node that wraps the hyerlink <span>
while (target && (!(target instanceof HTMLElement) || !target.dataset?.targethrefs)) target = target.parentElement;
const editor = this._editorView;
if (editor && target && !(e.nativeEvent instanceof simMouseEvent ? e.nativeEvent.dash : false)) {
@@ -789,10 +797,10 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
.lastElement()
.replace(Doc.localServerPath(), '')
.split('?')[0];
- const deleteMarkups = undoBatch(() => {
+ const deleteMarkups = undoable(() => {
const { selection } = editor.state;
editor.dispatch(editor.state.tr.removeMark(selection.from, selection.to, editor.state.schema.marks.linkAnchor));
- });
+ }, 'delete markups');
e.persist();
anchorDoc &&
DocServer.GetRefField(anchorDoc).then(
@@ -816,21 +824,21 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
const changeItems: ContextMenuProps[] = [];
changeItems.push({
description: 'plain',
- event: undoBatch(() => {
+ event: undoable(() => {
Doc.setNativeView(this.Document);
this.layoutDoc.layout_autoHeightMargins = undefined;
- }),
+ }, 'set plain view'),
icon: 'eye',
});
changeItems.push({
description: 'metadata',
- event: undoBatch(() => {
+ event: undoable(() => {
this.dataDoc.layout_meta = Cast(Doc.UserDoc().emptyHeader, Doc, null)?.layout;
this.Document.layout_fieldKey = 'layout_meta';
setTimeout(() => {
this.layoutDoc._header_height = this.layoutDoc._layout_autoHeightMargins = 50;
}, 50);
- }),
+ }, 'set metadata view'),
icon: 'eye',
});
const noteTypesDoc = Cast(Doc.UserDoc().template_notes, Doc, null);
@@ -838,11 +846,14 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
const icon: IconProp = StrCast(note.icon) as IconProp;
changeItems.push({
description: StrCast(note.title),
- event: undoBatch(() => {
- this.layoutDoc.layout_autoHeightMargins = undefined;
- Doc.setNativeView(this.Document);
- DocUtils.makeCustomViewClicked(this.Document, Docs.Create.TreeDocument, StrCast(note.title), note);
- }),
+ event: undoable(
+ () => {
+ this.layoutDoc.layout_autoHeightMargins = undefined;
+ Doc.setNativeView(this.Document);
+ DocUtils.makeCustomViewClicked(this.Document, Docs.Create.TreeDocument, StrCast(note.title), note);
+ },
+ `set ${StrCast(note.title)} view}`
+ ),
icon: icon,
});
});
@@ -1229,9 +1240,9 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
const protoData = DocCast(this.dataDoc.proto)?.[this.fieldKey];
const dataData = this.dataDoc[this.fieldKey];
const layoutData = Doc.AreProtosEqual(this.layoutDoc, this.dataDoc) ? undefined : this.layoutDoc[this.fieldKey];
- const dataTime = dataData ? DateCast(this.dataDoc[this.fieldKey + '_modificationDate'])?.date.getTime() ?? 0 : 0;
- const layoutTime = layoutData && this.dataDoc[this.fieldKey + '_autoUpdate'] ? DateCast(DocCast(this.layoutDoc)[this.fieldKey + '_modificationDate'])?.date.getTime() ?? 0 : 0;
- const protoTime = protoData && this.dataDoc[this.fieldKey + '_autoUpdate'] ? DateCast(DocCast(this.dataDoc.proto)[this.fieldKey + '_modificationDate'])?.date.getTime() ?? 0 : 0;
+ const dataTime = dataData ? (DateCast(this.dataDoc[this.fieldKey + '_modificationDate'])?.date.getTime() ?? 0) : 0;
+ const layoutTime = layoutData && this.dataDoc[this.fieldKey + '_autoUpdate'] ? (DateCast(DocCast(this.layoutDoc)[this.fieldKey + '_modificationDate'])?.date.getTime() ?? 0) : 0;
+ const protoTime = protoData && this.dataDoc[this.fieldKey + '_autoUpdate'] ? (DateCast(DocCast(this.dataDoc.proto)[this.fieldKey + '_modificationDate'])?.date.getTime() ?? 0) : 0;
const recentData = dataTime >= layoutTime ? (protoTime >= dataTime ? protoData : dataData) : layoutTime >= protoTime ? layoutData : protoData;
const whichData = recentData ?? (this.layoutDoc.isTemplateDoc ? layoutData : protoData) ?? protoData;
return !whichData ? undefined : { data: RTFCast(whichData), str: Field.toString(DocCast(whichData) ?? StrCast(whichData)) };
@@ -1370,11 +1381,13 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
}
richTextMenuPlugin() {
- return new Plugin({view : action((newView: EditorView) => {
+ return new Plugin({
+ view: action((newView: EditorView) => {
this._props.rootSelected?.() && RichTextMenu.Instance && (RichTextMenu.Instance.view = newView);
return new RichTextMenuPlugin({ editorProps: this._props });
- })});
- };
+ }),
+ });
+ }
_didScroll = false;
_scrollStopper: undefined | (() => void);
// eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -1509,7 +1522,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
e.preventDefault();
e.stopPropagation();
const timecode = Number(target.dataset?.timecode);
- DocServer.GetRefField(target.dataset?.audioid || "").then(anchor => {
+ DocServer.GetRefField(target.dataset?.audioid || '').then(anchor => {
if (anchor instanceof Doc) {
// const timecode = NumCast(anchor.timecodeToShow, 0);
const audiodoc = anchor.annotationOn as Doc;
@@ -1549,8 +1562,8 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
const state = this.EditorView?.state;
if (state && this.ProseRef?.children[0].className.includes('-focused') && this._props.isContentActive() && !e.button) {
if (!state.selection.empty && !(state.selection instanceof NodeSelection)) this.setupAnchorMenu();
- let clickTarget:HTMLElement|Element|null = e.target as HTMLElement; // hrefs are stored on the dataset of the <a> node that wraps the hyerlink <span>
- for (let target:HTMLElement|Element|null = clickTarget as HTMLElement; target instanceof HTMLElement && !target.dataset?.targethrefs; target = target.parentElement);
+ let clickTarget: HTMLElement | Element | null = e.target as HTMLElement; // hrefs are stored on the dataset of the <a> node that wraps the hyerlink <span>
+ for (let target: HTMLElement | Element | null = clickTarget as HTMLElement; target instanceof HTMLElement && !target.dataset?.targethrefs; target = target.parentElement);
while (clickTarget instanceof HTMLElement && !clickTarget.dataset?.targethrefs) clickTarget = clickTarget.parentElement;
const dataset = clickTarget instanceof HTMLElement ? clickTarget?.dataset : undefined;
FormattedTextBoxComment.update(this, this.EditorView!, undefined, dataset?.targethrefs, dataset?.linkdoc, dataset?.nopreview === 'true');
@@ -1588,7 +1601,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
onClick = (e: React.MouseEvent): void => {
if (!this._props.isContentActive()) return;
const editorView = this._editorView;
- const editorRoot = editorView?.root instanceof Document ?editorView.root : undefined;
+ const editorRoot = editorView?.root instanceof Document ? editorView.root : undefined;
if (editorView && (!this._forceUncollapse || editorRoot?.getSelection()?.isCollapsed)) {
// this is a hack to allow the cursor to be placed at the end of a document when the document ends in an inline dash comment. Apparently Chrome on Windows has a bug/feature which breaks this when clicking after the end of the text.
const pcords = editorView.posAtCoords({ left: e.clientX, top: e.clientY });
@@ -1834,7 +1847,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
TraceMobx();
const annotated = DocListCast(this.dataDoc[this.SidebarKey]).filter(d => d?.author).length;
const color = !annotated ? Colors.WHITE : Colors.BLACK;
- const backgroundColor = !annotated ? (this.sidebarWidth() ? Colors.MEDIUM_BLUE : Colors.BLACK) : this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.WidgetColor + (annotated ? ':annotated' : '')) as string;
+ const backgroundColor = !annotated ? (this.sidebarWidth() ? Colors.MEDIUM_BLUE : Colors.BLACK) : (this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.WidgetColor + (annotated ? ':annotated' : '')) as string);
return !annotated && (!this._props.isContentActive() || SnappingManager.IsDragging || Doc.ActiveTool !== InkTool.None) ? null : (
<div
@@ -1981,7 +1994,7 @@ export class FormattedTextBox extends ViewBoxAnnotatableComponent<FormattedTextB
@computed get fontColor() { return this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.FontColor) as string; } // prettier-ignore
@computed get fontSize() { return this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.FontSize) as string; } // prettier-ignore
@computed get fontFamily() { return this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.FontFamily) as string; } // prettier-ignore
- @computed get fontWeight() { return this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.FontWeight) as string; }// prettier-ignore
+ @computed get fontWeight() { return this._props.styleProvider?.(this.layoutDoc, this._props, StyleProp.FontWeight) as string; } // prettier-ignore
render() {
TraceMobx();
const scale = this._props.NativeDimScaling?.() || 1;
diff --git a/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx b/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx
index 37a96fc37..6c0eac103 100644
--- a/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx
+++ b/src/client/views/nodes/formattedText/FormattedTextBoxComment.tsx
@@ -61,8 +61,8 @@ export class FormattedTextBoxComment {
tooltip.style.display = 'none';
tooltip.appendChild(tooltipText);
tooltip.onpointerdown = (e: PointerEvent) => {
- const { textBox, startUserMarkRegion, endUserMarkRegion, userMark } = FormattedTextBoxComment;
- false && startUserMarkRegion !== undefined && textBox?.adoptAnnotation(startUserMarkRegion, endUserMarkRegion, userMark);
+ // const { textBox, startUserMarkRegion, endUserMarkRegion, userMark } = FormattedTextBoxComment;
+ // startUserMarkRegion !== undefined && textBox?.adoptAnnotation(startUserMarkRegion, endUserMarkRegion, userMark);
e.stopPropagation();
e.preventDefault();
};
diff --git a/src/client/views/nodes/formattedText/ParagraphNodeSpec.ts b/src/client/views/nodes/formattedText/ParagraphNodeSpec.ts
index 8799964b3..d41938698 100644
--- a/src/client/views/nodes/formattedText/ParagraphNodeSpec.ts
+++ b/src/client/views/nodes/formattedText/ParagraphNodeSpec.ts
@@ -1,18 +1,18 @@
-import { Node, DOMOutputSpec } from 'prosemirror-model';
+import { Node, DOMOutputSpec, AttributeSpec, TagParseRule } from 'prosemirror-model';
import clamp from '../../../util/clamp';
import convertToCSSPTValue from '../../../util/convertToCSSPTValue';
import toCSSLineSpacing from '../../../util/toCSSLineSpacing';
// import type { NodeSpec } from './Types';
type NodeSpec = {
- attrs?: { [key: string]: any };
+ attrs?: { [key: string]: AttributeSpec };
content?: string;
draggable?: boolean;
group?: string;
inline?: boolean;
name?: string;
- parseDOM?: Array<any>;
- toDOM?: (node: any) => DOMOutputSpec;
+ parseDOM?: Array<TagParseRule>;
+ toDOM?: (node: Node) => DOMOutputSpec;
};
// This assumes that every 36pt maps to one indent level.
@@ -30,7 +30,7 @@ function convertMarginLeftToIndentValue(marginLeft: string): number {
return clamp(MIN_INDENT_LEVEL, Math.floor(ptValue / INDENT_MARGIN_PT_SIZE), MAX_INDENT_LEVEL);
}
-function getAttrs(dom: HTMLElement): Object {
+export function getAttrs(dom: HTMLElement): object {
const { lineHeight, textAlign, marginLeft, paddingTop, paddingBottom } = dom.style;
let align = dom.getAttribute('align') || textAlign || '';
@@ -50,9 +50,31 @@ function getAttrs(dom: HTMLElement): Object {
return { align, indent, lineSpacing, paddingTop, paddingBottom, id };
}
-function toDOM(node: Node): DOMOutputSpec {
+export function getHeadingAttrs(dom: HTMLElement): { align?: string; indent?: number; lineSpacing?: string; paddingTop?: string; paddingBottom?: string; id: string; level?: number } {
+ const { lineHeight, textAlign, marginLeft, paddingTop, paddingBottom } = dom.style;
+
+ let align = dom.getAttribute('align') || textAlign || '';
+ align = ALIGN_PATTERN.test(align) ? align : '';
+
+ let indent = parseInt(dom.getAttribute(ATTRIBUTE_INDENT) || '', 10);
+
+ if (!indent && marginLeft) {
+ indent = convertMarginLeftToIndentValue(marginLeft);
+ }
+
+ indent = indent || MIN_INDENT_LEVEL;
+
+ const lineSpacing = lineHeight ? toCSSLineSpacing(lineHeight) : undefined;
+
+ const level = Number(dom.nodeName.substring(1)) || 1;
+
+ const id = dom.getAttribute('id') || '';
+ return { align, indent, lineSpacing, paddingTop, paddingBottom, id, level };
+}
+
+export function toDOM(node: Node): DOMOutputSpec {
const { align, indent, inset, lineSpacing, paddingTop, paddingBottom, id } = node.attrs;
- const attrs: { [key: string]: any } | null = {};
+ const attrs: { [key: string]: unknown } | null = {};
let style = '';
if (align && align !== 'left') {
diff --git a/src/client/views/nodes/formattedText/RichTextMenu.tsx b/src/client/views/nodes/formattedText/RichTextMenu.tsx
index 247b7c097..738f6d699 100644
--- a/src/client/views/nodes/formattedText/RichTextMenu.tsx
+++ b/src/client/views/nodes/formattedText/RichTextMenu.tsx
@@ -1,8 +1,8 @@
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { Tooltip } from '@mui/material';
-import { action, computed, IReactionDisposer, makeObservable, observable, reaction } from 'mobx';
+import { action, computed, IReactionDisposer, makeObservable, observable } from 'mobx';
import { observer } from 'mobx-react';
-import { lift, wrapIn } from 'prosemirror-commands';
+import { lift, toggleMark, wrapIn } from 'prosemirror-commands';
import { Mark, MarkType } from 'prosemirror-model';
import { wrapInList } from 'prosemirror-schema-list';
import { EditorState, NodeSelection, TextSelection, Transaction } from 'prosemirror-state';
@@ -22,8 +22,6 @@ import { updateBullets } from './ProsemirrorExampleTransfer';
import './RichTextMenu.scss';
import { schema } from './schema_rts';
-const { toggleMark } = require('prosemirror-commands');
-
@observer
export class RichTextMenu extends AntimodeMenu<AntimodeMenuProps> {
// eslint-disable-next-line no-use-before-define
@@ -35,8 +33,8 @@ export class RichTextMenu extends AntimodeMenu<AntimodeMenuProps> {
private _linkToRef = React.createRef<HTMLInputElement>();
layoutDoc: Doc | undefined;
- @observable public view?: EditorView & { TextView ?: FormattedTextBox } = undefined;
- public editorProps: FieldViewProps | AntimodeMenuProps |undefined;
+ @observable public view?: EditorView & { TextView?: FormattedTextBox } = undefined;
+ public editorProps: FieldViewProps | AntimodeMenuProps | undefined;
public _brushMap: Map<string, Set<Mark>> = new Map();
@@ -124,7 +122,7 @@ export class RichTextMenu extends AntimodeMenu<AntimodeMenuProps> {
}
@action
- public updateMenu(view: EditorView | undefined, lastState: EditorState | undefined, props: FormattedTextBoxProps|AntimodeMenuProps|undefined, layoutDoc: Doc | undefined) {
+ public updateMenu(view: EditorView | undefined, lastState: EditorState | undefined, props: FormattedTextBoxProps | AntimodeMenuProps | undefined, layoutDoc: Doc | undefined) {
if (this._linkToRef.current?.getBoundingClientRect().width) {
return;
}
@@ -158,7 +156,7 @@ export class RichTextMenu extends AntimodeMenu<AntimodeMenuProps> {
this.getTextLinkTargetTitle().then(targetTitle => this.setCurrentLink(targetTitle));
}
- setMark = (mark: Mark, state: EditorState, dispatch: (tr:Transaction) => void, dontToggle: boolean = false) => {
+ setMark = (mark: Mark, state: EditorState, dispatch: (tr: Transaction) => void, dontToggle: boolean = false) => {
if (mark) {
const newPos = state.selection.$anchor.node()?.type === schema.nodes.ordered_list ? state.selection.from : state.selection.from;
const node = (state.selection as NodeSelection).node ?? (newPos >= 0 ? state.doc.nodeAt(newPos) : undefined);
@@ -177,7 +175,7 @@ export class RichTextMenu extends AntimodeMenu<AntimodeMenuProps> {
toggleMark(mark.type, mark.attrs)(state, dispatch);
}
}
- // this.updateMenu(this.view, undefined, undefined, this.layoutDoc);
+ // this.updateMenu(this.view, undefined, undefined, this.layoutDoc);
}
};
@@ -193,7 +191,7 @@ export class RichTextMenu extends AntimodeMenu<AntimodeMenuProps> {
}
}
return 'left';
- }
+ };
// finds font sizes and families in selection
getActiveListStyle = () => {
@@ -208,7 +206,7 @@ export class RichTextMenu extends AntimodeMenu<AntimodeMenuProps> {
}
}
return '';
- }
+ };
// finds font sizes and families in selection
getActiveFontStylesOnSelection() {
@@ -365,7 +363,7 @@ export class RichTextMenu extends AntimodeMenu<AntimodeMenuProps> {
this.view.focus();
} else {
Doc.UserDoc()[fontField] = value;
- // this.updateMenu(this.view, undefined, this.props, this.layoutDoc);
+ // this.updateMenu(this.view, undefined, this.props, this.layoutDoc);
}
};
@@ -391,10 +389,10 @@ export class RichTextMenu extends AntimodeMenu<AntimodeMenuProps> {
this.view!.dispatch(tx3);
});
this.view.focus();
- // this.updateMenu(this.view, undefined, this.props, this.layoutDoc);
+ // this.updateMenu(this.view, undefined, this.props, this.layoutDoc);
};
- insertSummarizer(state: EditorState, dispatch: (tr:Transaction) => void) {
+ insertSummarizer(state: EditorState, dispatch: (tr: Transaction) => void) {
if (state.selection.empty) return false;
const mark = state.schema.marks.summarize.create();
const { tr } = state;
@@ -408,7 +406,7 @@ export class RichTextMenu extends AntimodeMenu<AntimodeMenuProps> {
vcenterToggle = () => {
this.layoutDoc && (this.layoutDoc._layout_centered = !this.layoutDoc._layout_centered);
};
- align = (view: EditorView, dispatch: (tr:Transaction) => void, alignment: 'left' | 'right' | 'center') => {
+ align = (view: EditorView, dispatch: (tr: Transaction) => void, alignment: 'left' | 'right' | 'center') => {
if (this.TextView?._props.rootSelected?.()) {
let { tr } = view.state;
view.state.doc.nodesBetween(view.state.selection.from, view.state.selection.to, (node, pos) => {
@@ -424,7 +422,7 @@ export class RichTextMenu extends AntimodeMenu<AntimodeMenuProps> {
}
};
- paragraphSetup(state: EditorState, dispatch: (tr:Transaction) => void, field: 'inset' | 'indent', value?: 0 | 10 | -10) {
+ paragraphSetup(state: EditorState, dispatch: (tr: Transaction) => void, field: 'inset' | 'indent', value?: 0 | 10 | -10) {
let { tr } = state;
state.doc.nodesBetween(state.selection.from, state.selection.to, (node, pos) => {
if (node.type === schema.nodes.paragraph || node.type === schema.nodes.heading) {
@@ -440,8 +438,8 @@ export class RichTextMenu extends AntimodeMenu<AntimodeMenuProps> {
return true;
}
- insertBlockquote(state: EditorState, dispatch: (tr:Transaction) => void) {
- const node = state.selection.$from.depth ? state.selection.$from.node(state.selection.$from.depth-1): undefined;
+ insertBlockquote(state: EditorState, dispatch: (tr: Transaction) => void) {
+ const node = state.selection.$from.depth ? state.selection.$from.node(state.selection.$from.depth - 1) : undefined;
if (node?.type === schema.nodes.blockquote) {
lift(state, dispatch);
} else {
@@ -450,7 +448,7 @@ export class RichTextMenu extends AntimodeMenu<AntimodeMenuProps> {
return true;
}
- insertHorizontalRule(state: EditorState, dispatch: (tr:Transaction) => void) {
+ insertHorizontalRule(state: EditorState, dispatch: (tr: Transaction) => void) {
dispatch(state.tr.replaceSelectionWith(state.schema.nodes.horizontal_rule.create()).scrollIntoView());
return true;
}
@@ -516,7 +514,7 @@ export class RichTextMenu extends AntimodeMenu<AntimodeMenuProps> {
const onLinkChange = (e: React.ChangeEvent<HTMLInputElement>) => {
this.TextView?.endUndoTypingBatch();
UndoManager.RunInBatch(() => this.setCurrentLink(e.target.value), 'link change');
- }
+ };
const link = this.currentLink ? this.currentLink : '';
@@ -595,7 +593,7 @@ export class RichTextMenu extends AntimodeMenu<AntimodeMenuProps> {
if (this.view) {
const linkAnchor = this.view.state.selection.$from.nodeAfter?.marks.find(m => m.type === this.view!.state.schema.marks.linkAnchor);
if (linkAnchor) {
- const allAnchors = (linkAnchor.attrs.allAnchors as { href: string; title: string; linkId: string; targetId: string; }[]).slice();
+ const allAnchors = (linkAnchor.attrs.allAnchors as { href: string; title: string; linkId: string; targetId: string }[]).slice();
this.TextView?.RemoveAnchorFromSelection(allAnchors);
// bcz: Argh ... this will remove the link from the document even it's anchored somewhere else in the text which happens if only part of the anchor text was selected.
allAnchors
@@ -698,7 +696,7 @@ interface RichTextMenuPluginProps {
}
export class RichTextMenuPlugin extends React.Component<RichTextMenuPluginProps> {
// eslint-disable-next-line react/no-unused-class-component-methods
- update(view: EditorView & {TextView ?: FormattedTextBox}, lastState: EditorState | undefined) {
+ update(view: EditorView & { TextView?: FormattedTextBox }, lastState: EditorState | undefined) {
RichTextMenu.Instance?.updateMenu(view, lastState, this.props.editorProps, view.TextView?.layoutDoc);
}
render() {
diff --git a/src/client/views/nodes/formattedText/RichTextRules.ts b/src/client/views/nodes/formattedText/RichTextRules.ts
index bf11dfe62..39f589b1e 100644
--- a/src/client/views/nodes/formattedText/RichTextRules.ts
+++ b/src/client/views/nodes/formattedText/RichTextRules.ts
@@ -1,4 +1,5 @@
import { ellipsis, emDash, InputRule, smartQuotes, textblockTypeInputRule } from 'prosemirror-inputrules';
+import { NodeType } from 'prosemirror-model';
import { NodeSelection, TextSelection } from 'prosemirror-state';
import { ClientUtils } from '../../../../ClientUtils';
import { Doc, DocListCast, FieldResult, StrListCast } from '../../../../fields/Doc';
@@ -6,7 +7,7 @@ import { DocData } from '../../../../fields/DocSymbols';
import { Id } from '../../../../fields/FieldSymbols';
import { List } from '../../../../fields/List';
import { NumCast, StrCast } from '../../../../fields/Types';
-import { Utils } from '../../../../Utils';
+import { emptyFunction, Utils } from '../../../../Utils';
import { Docs } from '../../../documents/Documents';
import { CollectionViewType } from '../../../documents/DocumentTypes';
import { DocUtils } from '../../../documents/DocUtils';
@@ -35,13 +36,7 @@ export class RichTextRules {
wrappingInputRule(/%>$/, schema.nodes.blockquote),
// 1. create numerical ordered list
- wrappingInputRule(
- /^1\.\s$/,
- schema.nodes.ordered_list,
- () => ({ mapStyle: 'decimal', bulletStyle: 1 }),
- (match: any, node: any) => node.childCount + node.attrs.order === +match[1],
- ((type: any) => ({ type: type, attrs: { mapStyle: 'decimal', bulletStyle: 1 } })) as any
- ),
+ wrappingInputRule(/^1\.\s$/, schema.nodes.ordered_list, () => ({ mapStyle: 'decimal', bulletStyle: 1 }), emptyFunction, ((type: unknown) => ({ type, attrs: { mapStyle: 'decimal', bulletStyle: 1 } })) as unknown as null),
// A. create alphabetical ordered list
wrappingInputRule(
@@ -49,9 +44,8 @@ export class RichTextRules {
schema.nodes.ordered_list,
// match => {
() => ({ mapStyle: 'multi', bulletStyle: 1 }),
- // return ({ order: +match[1] })
- (match: any, node: any) => node.childCount + node.attrs.order === +match[1],
- ((type: any) => ({ type: type, attrs: { mapStyle: 'multi', bulletStyle: 1 } })) as any
+ emptyFunction,
+ ((type: NodeType) => ({ type, attrs: { mapStyle: 'multi', bulletStyle: 1 } })) as unknown as null
),
// * + - create bullet list
@@ -60,8 +54,8 @@ export class RichTextRules {
schema.nodes.ordered_list,
// match => {
() => ({ mapStyle: 'bullet' }), // ({ order: +match[1] })
- (match: any, node: any) => node.childCount + node.attrs.order === +match[1],
- ((type: any) => ({ type: type, attrs: { mapStyle: 'bullet' } })) as any
+ emptyFunction,
+ ((type: NodeType) => ({ type: type, attrs: { mapStyle: 'bullet' } })) as unknown as null
),
// ``` create code block
@@ -93,7 +87,7 @@ export class RichTextRules {
const textDoc = this.Document[DocData];
const numInlines = NumCast(textDoc.inlineTextCount);
textDoc.inlineTextCount = numInlines + 1;
- const node = (state.doc.resolve(start) as any).nodeAfter;
+ const node = state.doc.resolve(start).nodeAfter;
const newNode = schema.nodes.dashComment.create({ docId: doc[Id], reflow: false });
const dashDoc = schema.nodes.dashDoc.create({ width: 75, height: 35, title: 'dashDoc', docId: doc[Id], float: 'right' });
const sm = state.storedMarks || undefined;
@@ -137,7 +131,7 @@ export class RichTextRules {
textDocInline.proto = textDoc; // make the annotation inherit from the outer text doc so that it can resolve any nested field references, e.g., [[field]]
textDoc[inlineLayoutKey] = FormattedTextBox.LayoutString(inlineFieldKey); // create a layout string for the layout key that will render the annotation text
textDoc[inlineFieldKey] = ''; // set a default value for the annotation
- const node = (state.doc.resolve(start) as any).nodeAfter;
+ const node = state.doc.resolve(start).nodeAfter;
const newNode = schema.nodes.dashComment.create({ docId: textDocInline[Id], reflow: true });
const dashDoc = schema.nodes.dashDoc.create({ width: 75, height: 35, title: 'dashDoc', docId: textDocInline[Id], float: 'right' });
const sm = state.storedMarks || undefined;
@@ -154,8 +148,8 @@ export class RichTextRules {
// set the First-line indent node type for the selection's paragraph (assumes % was used to initiate an EnteringStyle mode)
new InputRule(/(%d|d)$/, (state, match, start, end) => {
if (!match[0].startsWith('%') && !this.EnteringStyle) return null;
- const pos = state.doc.resolve(start) as any;
- for (let depth = pos.path.length / 3 - 1; depth >= 0; depth--) {
+ const pos = state.doc.resolve(start);
+ for (let depth = pos.depth; depth >= 0; depth--) {
const node = pos.node(depth);
if (node.type === schema.nodes.paragraph) {
const replaced = state.tr.setNodeMarkup(pos.pos - pos.parentOffset - 1, node.type, { ...node.attrs, indent: node.attrs.indent === 25 ? undefined : 25 });
@@ -169,8 +163,8 @@ export class RichTextRules {
// set the Hanging indent node type for the current selection's paragraph (assumes % was used to initiate an EnteringStyle mode)
new InputRule(/(%h|h)$/, (state, match, start, end) => {
if (!match[0].startsWith('%') && !this.EnteringStyle) return null;
- const pos = state.doc.resolve(start) as any;
- for (let depth = pos.path.length / 3 - 1; depth >= 0; depth--) {
+ const pos = state.doc.resolve(start);
+ for (let depth = pos.depth; depth >= 0; depth--) {
const node = pos.node(depth);
if (node.type === schema.nodes.paragraph) {
const replaced = state.tr.setNodeMarkup(pos.pos - pos.parentOffset - 1, node.type, { ...node.attrs, indent: node.attrs.indent === -25 ? undefined : -25 });
@@ -184,12 +178,12 @@ export class RichTextRules {
// set the Quoted indent node type for the current selection's paragraph (assumes % was used to initiate an EnteringStyle mode)
new InputRule(/(%q|q)$/, (state, match, start, end) => {
if (!match[0].startsWith('%') && !this.EnteringStyle) return null;
- const pos = state.doc.resolve(start) as any;
+ const pos = state.doc.resolve(start);
if (state.selection instanceof NodeSelection && state.selection.node.type === schema.nodes.ordered_list) {
const { node } = state.selection;
return state.tr.setNodeMarkup(pos.pos, node.type, { ...node.attrs, indent: node.attrs.indent === 30 ? undefined : 30 });
}
- for (let depth = pos.path.length / 3 - 1; depth >= 0; depth--) {
+ for (let depth = pos.depth; depth >= 0; depth--) {
const node = pos.node(depth);
if (node.type === schema.nodes.paragraph) {
const replaced = state.tr.setNodeMarkup(pos.pos - pos.parentOffset - 1, node.type, { ...node.attrs, inset: node.attrs.inset === 30 ? undefined : 30 });
@@ -202,9 +196,9 @@ export class RichTextRules {
// center justify text
new InputRule(/%\^/, (state, match, start, end) => {
- const resolved = state.doc.resolve(start) as any;
+ const resolved = state.doc.resolve(start);
if (resolved?.parent.type.name === 'paragraph') {
- return state.tr.deleteRange(start, end).setNodeMarkup(resolved.path[resolved.path.length - 4], schema.nodes.paragraph, { ...resolved.parent.attrs, align: 'center' }, resolved.parent.marks);
+ return state.tr.deleteRange(start, end).setNodeMarkup(resolved.start() - 1, schema.nodes.paragraph, { ...resolved.parent.attrs, align: 'center' }, resolved.parent.marks);
}
const node = resolved.nodeAfter;
const sm = state.storedMarks || undefined;
@@ -214,9 +208,9 @@ export class RichTextRules {
// left justify text
new InputRule(/%\[/, (state, match, start, end) => {
- const resolved = state.doc.resolve(start) as any;
+ const resolved = state.doc.resolve(start);
if (resolved?.parent.type.name === 'paragraph') {
- return state.tr.deleteRange(start, end).setNodeMarkup(resolved.path[resolved.path.length - 4], schema.nodes.paragraph, { ...resolved.parent.attrs, align: 'left' }, resolved.parent.marks);
+ return state.tr.deleteRange(start, end).setNodeMarkup(resolved.start() - 1, schema.nodes.paragraph, { ...resolved.parent.attrs, align: 'left' }, resolved.parent.marks);
}
const node = resolved.nodeAfter;
const sm = state.storedMarks || undefined;
@@ -226,9 +220,9 @@ export class RichTextRules {
// right justify text
new InputRule(/%\]/, (state, match, start, end) => {
- const resolved = state.doc.resolve(start) as any;
+ const resolved = state.doc.resolve(start);
if (resolved?.parent.type.name === 'paragraph') {
- return state.tr.deleteRange(start, end).setNodeMarkup(resolved.path[resolved.path.length - 4], schema.nodes.paragraph, { ...resolved.parent.attrs, align: 'right' }, resolved.parent.marks);
+ return state.tr.deleteRange(start, end).setNodeMarkup(resolved.start() - 1, schema.nodes.paragraph, { ...resolved.parent.attrs, align: 'right' }, resolved.parent.marks);
}
const node = resolved.nodeAfter;
const sm = state.storedMarks || undefined;
@@ -426,9 +420,9 @@ export class RichTextRules {
if (state.selection.to === state.selection.from || !this.EnteringStyle) return null;
const tag = match[0] === 't' ? 'todo' : match[0] === 'i' ? 'ignore' : match[0] === 'x' ? 'disagree' : match[0] === '!' ? 'important' : '??';
- const node = (state.doc.resolve(start) as any).nodeAfter;
+ const node = state.doc.resolve(start).nodeAfter;
- if (node?.marks.findIndex((m: any) => m.type === schema.marks.user_tag) !== -1) return state.tr.removeMark(start, end, schema.marks.user_tag);
+ if (node?.marks.findIndex(m => m.type === schema.marks.user_tag) !== -1) return state.tr.removeMark(start, end, schema.marks.user_tag);
return node
? state.tr
.removeMark(start, end, schema.marks.user_mark)
@@ -438,7 +432,7 @@ export class RichTextRules {
}),
new InputRule(/%\(/, (state, match, start, end) => {
- const node = (state.doc.resolve(start) as any).nodeAfter;
+ const node = state.doc.resolve(start).nodeAfter;
const sm = state.storedMarks?.slice() || [];
const mark = state.schema.marks.summarizeInclusive.create();
@@ -447,7 +441,7 @@ export class RichTextRules {
const content = selected.selection.content();
const replaced = node ? selected.replaceRangeWith(start, end, schema.nodes.summary.create({ visibility: true, text: content, textslice: content.toJSON() })) : state.tr;
- return replaced.setSelection(new TextSelection(replaced.doc.resolve(end))).setStoredMarks([...node.marks, ...sm]);
+ return replaced.setSelection(new TextSelection(replaced.doc.resolve(end))).setStoredMarks([...(node?.marks ?? []), ...sm]);
}),
new InputRule(/%\)/, (state, match, start, end) => state.tr.deleteRange(start, end).removeStoredMark(state.schema.marks.summarizeInclusive.create())),
diff --git a/src/client/views/nodes/formattedText/marks_rts.ts b/src/client/views/nodes/formattedText/marks_rts.ts
index 6e1f325cf..ba8e4faed 100644
--- a/src/client/views/nodes/formattedText/marks_rts.ts
+++ b/src/client/views/nodes/formattedText/marks_rts.ts
@@ -34,14 +34,14 @@ export const marks: { [index: string]: MarkSpec } = {
parseDOM: [
{
tag: 'a[href]',
- getAttrs(dom: any) {
+ getAttrs: dom => {
return {
title: dom.getAttribute('title'),
};
},
},
],
- toDOM(node: any) {
+ toDOM: node => {
const targethrefs = node.attrs.allAnchors.reduce((p: string, item: { href: string; title: string; anchorId: string }) => (p ? p + ' ' + item.href : item.href), '');
const anchorids = node.attrs.allAnchors.reduce((p: string, item: { href: string; title: string; anchorId: string }) => (p ? p + ' ' + item.anchorId : item.anchorId), '');
return ['a', { id: Utils.GenerateGuid(), class: anchorids, 'data-targethrefs': targethrefs, /* 'data-noPreview': 'true', */ 'data-linkdoc': node.attrs.linkDoc, title: node.attrs.title, style: `background: lightBlue` }, 0];
@@ -53,7 +53,7 @@ export const marks: { [index: string]: MarkSpec } = {
parseDOM: [
{
tag: 'div',
- getAttrs(dom: any) {
+ getAttrs: dom => {
return {
noAutoLink: dom.getAttribute('data-noAutoLink'),
};
@@ -80,7 +80,7 @@ export const marks: { [index: string]: MarkSpec } = {
parseDOM: [
{
tag: 'a[href]',
- getAttrs(dom: any) {
+ getAttrs: dom => {
return {
title: dom.getAttribute('title'),
noPreview: dom.getAttribute('noPreview'),
@@ -88,7 +88,7 @@ export const marks: { [index: string]: MarkSpec } = {
},
},
],
- toDOM(node: any) {
+ toDOM: node => {
const targethrefs = node.attrs.allAnchors.reduce((p: string, item: { href: string; title: string; anchorId: string }) => (p ? p + ' ' + item.href : item.href), '');
const anchorids = node.attrs.allAnchors.reduce((p: string, item: { href: string; title: string; anchorId: string }) => (p ? p + ' ' + item.anchorId : item.anchorId), '');
return node.attrs.docref && node.attrs.title
@@ -117,7 +117,7 @@ export const marks: { [index: string]: MarkSpec } = {
parseDOM: [
{
tag: 'span',
- getAttrs(dom: any) {
+ getAttrs: dom => {
return { fontSize: dom.style.fontSize ? dom.style.fontSize.toString() : '' };
},
},
@@ -131,7 +131,7 @@ export const marks: { [index: string]: MarkSpec } = {
parseDOM: [
{
tag: 'span',
- getAttrs(dom: any) {
+ getAttrs: dom => {
const cstyle = getComputedStyle(dom);
if (cstyle.font) {
if (cstyle.font.indexOf('Times New Roman') !== -1) return { fontFamily: 'Times New Roman' };
@@ -154,7 +154,7 @@ export const marks: { [index: string]: MarkSpec } = {
parseDOM: [
{
tag: 'span',
- getAttrs(dom: any) {
+ getAttrs: dom => {
return { color: dom.getAttribute('color') };
},
},
@@ -170,12 +170,12 @@ export const marks: { [index: string]: MarkSpec } = {
parseDOM: [
{
tag: 'span',
- getAttrs(dom: any) {
+ getAttrs: dom => {
return { fontHighlight: dom.getAttribute('background-color') };
},
},
],
- toDOM(node: any) {
+ toDOM: node => {
return node.attrs.fontHighlight ? ['span', { style: 'background-color:' + node.attrs.fontHighlight }] : ['span', { style: 'background-color: transparent' }];
},
},
@@ -224,7 +224,7 @@ export const marks: { [index: string]: MarkSpec } = {
attrs: {
bulletType: { default: 'decimal' },
},
- toDOM(node: any) {
+ toDOM: node => {
return [
'span',
{
@@ -238,11 +238,11 @@ export const marks: { [index: string]: MarkSpec } = {
parseDOM: [
{
tag: 'span',
- getAttrs: (p: any) => {
+ getAttrs: p => {
if (typeof p !== 'string') {
const style = getComputedStyle(p);
if (style.textDecoration === 'underline') return null;
- if (p.parentElement.outerHTML.indexOf('text-decoration: underline') !== -1 && p.parentElement.outerHTML.indexOf('text-decoration-style: solid') !== -1) {
+ if (p.parentElement?.outerHTML.indexOf('text-decoration: underline') !== -1 && p.parentElement?.outerHTML.indexOf('text-decoration-style: solid') !== -1) {
return null;
}
}
@@ -266,11 +266,11 @@ export const marks: { [index: string]: MarkSpec } = {
parseDOM: [
{
tag: 'span',
- getAttrs: (p: any) => {
+ getAttrs: p => {
if (typeof p !== 'string') {
const style = getComputedStyle(p);
if (style.textDecoration === 'underline') return null;
- if (p.parentElement.outerHTML.indexOf('text-decoration: underline') !== -1 && p.parentElement.outerHTML.indexOf('text-decoration-style: dotted') !== -1) {
+ if (p.parentElement?.outerHTML.indexOf('text-decoration: underline') !== -1 && p.parentElement?.outerHTML.indexOf('text-decoration-style: dotted') !== -1) {
return null;
}
}
@@ -292,10 +292,10 @@ export const marks: { [index: string]: MarkSpec } = {
parseDOM: [
{
tag: 'span',
- getAttrs: (p: any) => {
+ getAttrs: p => {
if (typeof p !== 'string') {
const style = getComputedStyle(p);
- if (style.textDecoration === 'underline' || p.parentElement.outerHTML.indexOf('text-decoration-style:line') !== -1) {
+ if (style.textDecoration === 'underline' || p.parentElement?.outerHTML.indexOf('text-decoration-style:line') !== -1) {
return null;
}
}
@@ -317,7 +317,7 @@ export const marks: { [index: string]: MarkSpec } = {
selected: { default: false },
},
parseDOM: [{ style: 'background: yellow' }],
- toDOM(node: any) {
+ toDOM: node => {
return ['span', { style: `background: ${node.attrs.selected ? 'orange' : 'yellow'}` }];
},
},
@@ -330,7 +330,7 @@ export const marks: { [index: string]: MarkSpec } = {
},
excludes: 'user_mark',
group: 'inline',
- toDOM(node: any) {
+ toDOM: node => {
const uid = node.attrs.userid.replace(/\./g, '').replace(/@/g, '');
const min = Math.round(node.attrs.modified / 60);
const hr = Math.round(min / 60);
@@ -348,7 +348,7 @@ export const marks: { [index: string]: MarkSpec } = {
},
group: 'inline',
inclusive: false,
- toDOM(node: any) {
+ toDOM: node => {
const uid = node.attrs.userid.replace('.', '').replace('@', '');
return ['span', { class: 'UT-' + uid + ' UT-' + node.attrs.tag }, 0];
},
diff --git a/src/client/views/nodes/formattedText/nodes_rts.ts b/src/client/views/nodes/formattedText/nodes_rts.ts
index 5bf942218..02ded3103 100644
--- a/src/client/views/nodes/formattedText/nodes_rts.ts
+++ b/src/client/views/nodes/formattedText/nodes_rts.ts
@@ -1,6 +1,6 @@
import { DOMOutputSpec, Node, NodeSpec } from 'prosemirror-model';
import { listItem, orderedList } from 'prosemirror-schema-list';
-import { ParagraphNodeSpec, toParagraphDOM, getParagraphNodeAttrs } from './ParagraphNodeSpec';
+import { ParagraphNodeSpec, toParagraphDOM, getHeadingAttrs } from './ParagraphNodeSpec';
import { DocServer } from '../../../DocServer';
import { Doc, Field, FieldType } from '../../../../fields/Doc';
import { schema } from './schema_rts';
@@ -53,7 +53,7 @@ export const nodes: { [index: string]: NodeSpec } = {
parseDOM: [
{
tag: 'audiotag',
- getAttrs(dom: any) {
+ getAttrs: dom => {
return {
timeCode: dom.getAttribute('data-timecode'),
audioId: dom.getAttribute('data-audioid'),
@@ -123,24 +123,57 @@ export const nodes: { [index: string]: NodeSpec } = {
level: { default: 1 },
},
parseDOM: [
- { tag: 'h1', attrs: { level: 1 } },
- { tag: 'h2', attrs: { level: 2 } },
- { tag: 'h3', attrs: { level: 3 } },
- { tag: 'h4', attrs: { level: 4 } },
- { tag: 'h5', attrs: { level: 5 } },
- { tag: 'h6', attrs: { level: 6 } },
+ {
+ tag: 'h1',
+ attrs: { level: 1 },
+ getAttrs(dom) {
+ return getHeadingAttrs(dom);
+ },
+ },
+ {
+ tag: 'h2',
+ attrs: { level: 2 },
+ getAttrs(dom) {
+ return getHeadingAttrs(dom);
+ },
+ },
+ {
+ tag: 'h3',
+ attrs: { level: 3 },
+ getAttrs(dom) {
+ return getHeadingAttrs(dom);
+ },
+ },
+ {
+ tag: 'h4',
+ attrs: { level: 4 },
+ getAttrs(dom) {
+ return getHeadingAttrs(dom);
+ },
+ },
+ {
+ tag: 'h5',
+ attrs: { level: 5 },
+ getAttrs(dom) {
+ return getHeadingAttrs(dom);
+ },
+ },
+ {
+ tag: 'h6',
+ attrs: { level: 6 },
+ getAttrs(dom) {
+ return getHeadingAttrs(dom);
+ },
+ },
],
toDOM(node) {
- const dom = toParagraphDOM(node) as any;
- dom[0] = `h${node.attrs.level || 1}`;
+ const dom = toParagraphDOM(node);
+ if (dom instanceof Array) {
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ (dom as any)[0] = `h${node.attrs.level || 1}`; // [0] is readonly so cast away to any
+ }
return dom;
},
- getAttrs(dom: any) {
- const attrs = getParagraphNodeAttrs(dom) as any;
- const level = Number(dom.nodeName.substring(1)) || 1;
- attrs.level = level;
- return attrs;
- },
},
// :: NodeSpec A code listing. Disallows marks or non-text inline
@@ -221,7 +254,7 @@ export const nodes: { [index: string]: NodeSpec } = {
parseDOM: [
{
tag: 'img[src]',
- getAttrs(dom: any) {
+ getAttrs: dom => {
return {
src: dom.getAttribute('src'),
title: dom.getAttribute('title'),
@@ -300,7 +333,7 @@ export const nodes: { [index: string]: NodeSpec } = {
parseDOM: [
{
tag: 'video[src]',
- getAttrs(dom: any) {
+ getAttrs: dom => {
return {
src: dom.getAttribute('src'),
title: dom.getAttribute('title'),
@@ -341,33 +374,31 @@ export const nodes: { [index: string]: NodeSpec } = {
parseDOM: [
{
tag: 'ul',
- getAttrs(dom: any) {
+ getAttrs: dom => {
return {
bulletStyle: dom.getAttribute('data-bulletStyle'),
mapStyle: dom.getAttribute('data-mapStyle'),
fontColor: dom.style.color,
- fontSize: dom.style['font-size'],
- fontFamily: dom.style['font-family'],
- indent: dom.style['margin-left'],
+ fontSize: dom.style.fontSize,
+ fontFamily: dom.style.fontFamily,
+ indent: dom.style.marginLeft,
};
},
},
{
style: 'list-style-type=disc',
- getAttrs() {
- return { mapStyle: 'bullet' };
- },
+ getAttrs: () => ({ mapStyle: 'bullet' }),
},
{
tag: 'ol',
- getAttrs(dom: any) {
+ getAttrs: dom => {
return {
bulletStyle: dom.getAttribute('data-bulletStyle'),
mapStyle: dom.getAttribute('data-mapStyle'),
fontColor: dom.style.color,
- fontSize: dom.style['font-size'],
- fontFamily: dom.style['font-family'],
- indent: dom.style['margin-left'],
+ fontSize: dom.style.fontSize,
+ fontFamily: dom.style.fontFamily,
+ indent: dom.style.marginLeft,
};
},
},
@@ -416,7 +447,7 @@ export const nodes: { [index: string]: NodeSpec } = {
parseDOM: [
{
tag: 'li',
- getAttrs(dom: any) {
+ getAttrs: dom => {
return { mapStyle: dom.getAttribute('data-mapStyle'), bulletStyle: dom.getAttribute('data-bulletStyle') };
},
},
diff --git a/src/client/views/pdf/GPTPopup/GPTPopup.tsx b/src/client/views/pdf/GPTPopup/GPTPopup.tsx
index cb5aad32d..0920b1bd3 100644
--- a/src/client/views/pdf/GPTPopup/GPTPopup.tsx
+++ b/src/client/views/pdf/GPTPopup/GPTPopup.tsx
@@ -1,4 +1,3 @@
-/* eslint-disable jsx-a11y/label-has-associated-control */
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { Button, IconButton, Type } from 'browndash-components';
import { action, makeObservable, observable } from 'mobx';
@@ -150,7 +149,7 @@ export class GPTPopup extends ObservableReactComponent<GPTPopupProps> {
}
public addDoc: (doc: Doc | Doc[], sidebarKey?: string | undefined) => boolean = () => false;
- public createFilteredDoc: (axes?: any) => boolean = () => false;
+ public createFilteredDoc: (axes?: string[]) => boolean = () => false;
public addToCollection: ((doc: Doc | Doc[], annotationKey?: string | undefined) => boolean) | undefined;
/**
@@ -371,8 +370,8 @@ export class GPTPopup extends ObservableReactComponent<GPTPopupProps> {
<div style={{ display: 'flex', flexDirection: 'column', gap: '1rem' }}>
{this.heading('GENERATED IMAGE')}
<div className="image-content-wrapper">
- {this.imgUrls.map(rawSrc => (
- <div className="img-wrapper">
+ {this.imgUrls.map((rawSrc, i) => (
+ <div key={rawSrc[0] + i} className="img-wrapper">
<div className="img-container">
<img key={rawSrc[0]} src={rawSrc[0]} width={150} height={150} alt="dalle generation" />
</div>
diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx
index 1279563ef..dee0edfae 100644
--- a/src/client/views/pdf/PDFViewer.tsx
+++ b/src/client/views/pdf/PDFViewer.tsx
@@ -1,8 +1,8 @@
import { action, computed, IReactionDisposer, makeObservable, observable, ObservableMap, reaction, runInAction } from 'mobx';
import { observer } from 'mobx-react';
import * as Pdfjs from 'pdfjs-dist';
-import 'pdfjs-dist/web/pdf_viewer.css';
import * as PDFJSViewer from 'pdfjs-dist/web/pdf_viewer.mjs';
+import 'pdfjs-dist/webpack.mjs'; // sets the PDF workerSrc
import * as React from 'react';
import { addStyleSheet, addStyleSheetRule, clearStyleSheetRules, ClientUtils, returnAll, returnFalse, returnNone, returnZero, smoothScroll } from '../../../ClientUtils';
import { CreateLinkToActiveAudio, Doc, DocListCast, Opt } from '../../../fields/Doc';
@@ -28,10 +28,8 @@ import { AnchorMenu } from './AnchorMenu';
import { Annotation } from './Annotation';
import { GPTPopup } from './GPTPopup/GPTPopup';
import './PDFViewer.scss';
-
-// pdfjsLib.GlobalWorkerOptions.workerSrc = `/assets/pdf.worker.js`;
// The workerSrc property shall be specified.
-Pdfjs.GlobalWorkerOptions.workerSrc = 'https://unpkg.com/pdfjs-dist@4.4.168/build/pdf.worker.mjs';
+// Pdfjs.GlobalWorkerOptions.workerSrc = 'https://unpkg.com/pdfjs-dist@4.4.168/build/pdf.worker.mjs';
interface IViewerProps extends FieldViewProps {
pdfBox: PDFBox;
@@ -62,7 +60,7 @@ export class PDFViewer extends ObservableReactComponent<IViewerProps> {
}
@observable _pageSizes: { width: number; height: number }[] = [];
- @observable _savedAnnotations = new ObservableMap<number, (HTMLDivElement & { marqueeing?: boolean})[]>();
+ @observable _savedAnnotations = new ObservableMap<number, (HTMLDivElement & { marqueeing?: boolean })[]>();
@observable _textSelecting = true;
@observable _showWaiting = true;
@observable Index: number = -1;
@@ -214,7 +212,7 @@ export class PDFViewer extends ObservableReactComponent<IViewerProps> {
this._disposers.scale = reaction(
() => NumCast(this._props.layoutDoc._freeform_scale, 1),
scale => {
- this._pdfViewer.currentScaleValue = scale+"";
+ this._pdfViewer.currentScaleValue = scale + '';
},
{ fireImmediately: true }
);
@@ -483,7 +481,7 @@ export class PDFViewer extends ObservableReactComponent<IViewerProps> {
e.stopPropagation();
if (e.ctrlKey) {
const curScale = Number(this._pdfViewer.currentScaleValue);
- this._pdfViewer.currentScaleValue = Math.max(1, Math.min(10, curScale - (curScale * e.deltaY) / 1000)) + "";
+ this._pdfViewer.currentScaleValue = Math.max(1, Math.min(10, curScale - (curScale * e.deltaY) / 1000)) + '';
this._props.layoutDoc._freeform_scale = Number(this._pdfViewer.currentScaleValue);
}
}