diff --git a/src/public/app/components/app_context.ts b/src/public/app/components/app_context.ts
index 4916340b1..16d2d5920 100644
--- a/src/public/app/components/app_context.ts
+++ b/src/public/app/components/app_context.ts
@@ -173,6 +173,7 @@ export type CommandMappings = {
moveBranchIdsTo: CommandData & {
branchIds: string[];
};
+ /** Sets the active {@link Screen} (e.g. to toggle the tree sidebar). It triggers the {@link EventMappings.activeScreenChanged} event, but only if the provided screen is different than the current one. */
setActiveScreen: CommandData & {
screen: Screen;
}
@@ -202,6 +203,10 @@ type EventMappings = {
},
readOnlyTemporarilyDisabled: {
noteContext: NoteContext
+ },
+ /** Triggered when the {@link CommandMappings.setActiveScreen} command is invoked. */
+ activeScreenChanged: {
+ activeScreen: Screen;
}
}
diff --git a/src/public/app/components/mobile_screen_switcher.ts b/src/public/app/components/mobile_screen_switcher.ts
index 02780354c..217bbc3fe 100644
--- a/src/public/app/components/mobile_screen_switcher.ts
+++ b/src/public/app/components/mobile_screen_switcher.ts
@@ -1,5 +1,5 @@
import Component from "./component.js";
-import appContext, { CommandListener, CommandListenerData } from "./app_context.js";
+import type { CommandListener, CommandListenerData } from "./app_context.js";
export type Screen = "detail" | "tree";
diff --git a/src/public/app/widgets/basic_widget.ts b/src/public/app/widgets/basic_widget.ts
index 55b4c512e..7be37a00a 100644
--- a/src/public/app/widgets/basic_widget.ts
+++ b/src/public/app/widgets/basic_widget.ts
@@ -9,7 +9,7 @@ import toastService from "../services/toast.js";
* For information on using widgets, see the tutorial {@tutorial widget_basics}.
*/
class BasicWidget extends Component {
- private attrs: Record;
+ protected attrs: Record;
private classes: string[];
private childPositionCounter: number;
private cssEl?: string;
diff --git a/src/public/app/widgets/containers/flex_container.js b/src/public/app/widgets/containers/flex_container.ts
similarity index 80%
rename from src/public/app/widgets/containers/flex_container.js
rename to src/public/app/widgets/containers/flex_container.ts
index ae3ffb107..095bc35b6 100644
--- a/src/public/app/widgets/containers/flex_container.js
+++ b/src/public/app/widgets/containers/flex_container.ts
@@ -1,7 +1,10 @@
import Container from "./container.js";
+export type FlexDirection = "row" | "column";
+
export default class FlexContainer extends Container {
- constructor(direction) {
+
+ constructor(direction: FlexDirection) {
super();
if (!direction || !['row', 'column'].includes(direction)) {
diff --git a/src/public/app/widgets/mobile_widgets/sidebar_container.js b/src/public/app/widgets/mobile_widgets/sidebar_container.ts
similarity index 66%
rename from src/public/app/widgets/mobile_widgets/sidebar_container.js
rename to src/public/app/widgets/mobile_widgets/sidebar_container.ts
index e401ef9f2..4c523163c 100644
--- a/src/public/app/widgets/mobile_widgets/sidebar_container.js
+++ b/src/public/app/widgets/mobile_widgets/sidebar_container.ts
@@ -1,4 +1,6 @@
-import FlexContainer from "../containers/flex_container.js";
+import { EventData } from "../../components/app_context.js";
+import { Screen } from "../../components/mobile_screen_switcher.js";
+import FlexContainer, { FlexDirection } from "../containers/flex_container.js";
const DRAG_STATE_NONE = 0;
const DRAG_STATE_INITIAL_DRAG = 1;
@@ -9,12 +11,25 @@ const DRAG_THRESHOLD = 10;
export default class SidebarContainer extends FlexContainer {
- constructor(screenName, direction) {
+ private screenName: Screen;
+ private currentTranslate: number;
+ private dragState: number;
+ private startX?: number;
+ private translatePercentage: number;
+ private sidebarEl!: HTMLElement;
+ private backdropEl!: HTMLElement;
+ private originalSidebarTransition: string;
+ private originalBackdropTransition: string;
+
+ constructor(screenName: Screen, direction: FlexDirection) {
super(direction);
this.screenName = screenName;
this.currentTranslate = -100;
+ this.translatePercentage = 0;
this.dragState = DRAG_STATE_NONE;
+ this.originalSidebarTransition = "";
+ this.originalBackdropTransition = "";
}
doRender() {
@@ -31,8 +46,8 @@ export default class SidebarContainer extends FlexContainer {
document.addEventListener("touchend", (e) => this.#onDragEnd(e));
}
- #onDragStart(e) {
- const x = e.touches ? e.touches[0].clientX : e.clientX;
+ #onDragStart(e: TouchEvent | MouseEvent) {
+ const x = "touches" in e ? e.touches[0].clientX : e.clientX;
this.startX = x;
if (x > 30 && this.currentTranslate === -100) {
@@ -44,12 +59,12 @@ export default class SidebarContainer extends FlexContainer {
this.translatePercentage = 0;
}
- #onDragMove(e) {
- if (this.dragState === DRAG_STATE_NONE) {
+ #onDragMove(e: TouchEvent | MouseEvent) {
+ if (this.dragState === DRAG_STATE_NONE || !this.startX) {
return;
}
- const x = e.touches ? e.touches[0].clientX : e.clientX;
+ const x = "touches" in e ? e.touches[0].clientX : e.clientX;
const deltaX = x - this.startX;
if (this.dragState === DRAG_STATE_INITIAL_DRAG) {
if (Math.abs(deltaX) > 10) {
@@ -57,7 +72,7 @@ export default class SidebarContainer extends FlexContainer {
this.sidebarEl.style.transition = "none";
this.backdropEl.style.transition = "none";
- this.backdropEl.style.opacity = (this.currentTranslate === -100 ? 0 : 1);
+ this.backdropEl.style.opacity = String(this.currentTranslate === -100 ? 0 : 1);
this.backdropEl.classList.add("show");
this.dragState = DRAG_STATE_DRAGGING;
@@ -67,13 +82,13 @@ export default class SidebarContainer extends FlexContainer {
const translatePercentage = Math.min(0, Math.max(this.currentTranslate + (deltaX / width) * 100, -100));
this.translatePercentage = translatePercentage;
this.sidebarEl.style.transform = `translateX(${translatePercentage}%)`;
- this.backdropEl.style.opacity = Math.max(0, 1 + (translatePercentage / 100));
+ this.backdropEl.style.opacity = String(Math.max(0, 1 + (translatePercentage / 100)));
}
e.preventDefault();
}
- #onDragEnd(e) {
+ #onDragEnd(e: TouchEvent | MouseEvent) {
if (this.dragState === DRAG_STATE_NONE) {
return;
}
@@ -96,13 +111,20 @@ export default class SidebarContainer extends FlexContainer {
return;
}
- this.sidebarEl = document.getElementById("mobile-sidebar-wrapper");
- this.backdropEl = document.getElementById("mobile-sidebar-container");
+ const sidebarEl = document.getElementById("mobile-sidebar-wrapper");
+ const backdropEl = document.getElementById("mobile-sidebar-container");
+
+ if (!sidebarEl || !backdropEl) {
+ throw new Error("Unable to find the sidebar or backdrop.");
+ }
+
+ this.sidebarEl = sidebarEl;
+ this.backdropEl = backdropEl;
this.originalSidebarTransition = this.sidebarEl.style.transition;
this.originalBackdropTransition = this.backdropEl.style.transition;
}
- #setSidebarOpen(isOpen) {
+ #setSidebarOpen(isOpen: boolean) {
if (!this.sidebarEl) {
return;
}
@@ -113,13 +135,13 @@ export default class SidebarContainer extends FlexContainer {
this.backdropEl.classList.toggle("show", isOpen);
this.backdropEl.style.transition = this.originalBackdropTransition;
- this.backdropEl.style.opacity = isOpen ? 1 : 0;
+ this.backdropEl.style.opacity = String(isOpen ? 1 : 0);
this.currentTranslate = isOpen ? 0 : -100;
this.dragState = DRAG_STATE_NONE;
}
- activeScreenChangedEvent({activeScreen}) {
+ activeScreenChangedEvent({activeScreen}: EventData<"activeScreenChanged">) {
this.#setInitialState();
this.#setSidebarOpen(activeScreen === this.screenName);
}