diff --git a/package-lock.json b/package-lock.json
index bc6814608f09a8cc199c43c5032ebf2b25d5cd11..e4144a016c1a7ebdb30a33ef67553d6cf351de40 100644
Binary files a/package-lock.json and b/package-lock.json differ
diff --git a/package.json b/package.json
index 1174bf125bff035e04d4d475054861ef5c765650..a6d47ae62eacfae1ed86cf3a366589a0d5b6e663 100644
--- a/package.json
+++ b/package.json
@@ -119,7 +119,7 @@
     "stream-browserify": "^3.0.0",
     "style-loader": "^2.0.0",
     "ts-jest": "^26.4.4",
-    "typescript": "^4.2.4",
+    "typescript": "^4.4.2",
     "webpack": "^5.37.1",
     "webpack-cli": "^4.7.0",
     "webpack-version-file-plugin": "^0.4.0"
@@ -141,14 +141,14 @@
     "cors": "^2.8.5",
     "express": "^4.17.1",
     "h264-mp4-encoder": "^1.0.12",
-    "immer": "^8.0.1",
+    "immer": "^9.0.6",
     "immutable": "^3.8.2",
     "node-fetch": "^2.6.1",
-    "react": "^17.0.1",
-    "react-dom": "^17.0.1",
-    "rxjs": "^6.6.6",
+    "react": "^17.0.2",
+    "react-dom": "^17.0.2",
+    "rxjs": "^7.3.0",
     "swagger-ui-dist": "^3.37.2",
-    "tslib": "^2.1.0",
+    "tslib": "^2.3.1",
     "util.promisify": "^1.0.1",
     "xhr2": "^0.2.0"
   }
diff --git a/src/apps/viewer/index.ts b/src/apps/viewer/index.ts
index 4943ad390b30f6b3f5c5a23ff1a98e6a6d71f74d..2ffa3624d8e73538b25e234343753eeb491aacd2 100644
--- a/src/apps/viewer/index.ts
+++ b/src/apps/viewer/index.ts
@@ -325,7 +325,7 @@ export class Viewer {
     }
 
     handleResize() {
-        this.plugin.layout.events.updated.next();
+        this.plugin.layout.events.updated.next(void 0);
     }
 }
 
diff --git a/src/cli/cifschema/util/cif-dic.ts b/src/cli/cifschema/util/cif-dic.ts
index b2979a67c7a2abbc78abb23e34067edfe3d91ccc..512d5de155f6bae6cd11830201b6891e2c3efb5c 100644
--- a/src/cli/cifschema/util/cif-dic.ts
+++ b/src/cli/cifschema/util/cif-dic.ts
@@ -372,7 +372,7 @@ export function generateSchema(frames: CifFrame[], imports: Imports = new Map())
             const parent_name = item_linked.getField('parent_name');
             if (child_name && parent_name) {
                 for (let i = 0; i < item_linked.rowCount; ++i) {
-                    const childName = child_name.str(i);
+                    const childName: string = child_name.str(i);
                     const parentName = parent_name.str(i);
                     if (childName in links && links[childName] !== parentName) {
                         console.log(`${childName} linked to ${links[childName]}, ignoring link to ${parentName}`);
diff --git a/src/mol-canvas3d/canvas3d.ts b/src/mol-canvas3d/canvas3d.ts
index 02366cb75cf072b0088e99a2b07e0dfdc5ee863e..d28751fe5a906c44bcb96e932e14922d43561919 100644
--- a/src/mol-canvas3d/canvas3d.ts
+++ b/src/mol-canvas3d/canvas3d.ts
@@ -732,7 +732,7 @@ namespace Canvas3D {
             resized,
             setProps: (properties, doNotRequestDraw = false) => {
                 const props: PartialCanvas3DProps = typeof properties === 'function'
-                    ? produce(getProps(), properties)
+                    ? produce(getProps(), properties as any)
                     : properties;
 
                 const cameraState: Partial<Camera.Snapshot> = Object.create(null);
diff --git a/src/mol-model-props/computed/interactions/contacts-builder.ts b/src/mol-model-props/computed/interactions/contacts-builder.ts
index bd70720ae0e66b020e31511bb50c11f2ee1a67ec..455d9b5a6abdb1f480f8535036825cd7a43f4643 100644
--- a/src/mol-model-props/computed/interactions/contacts-builder.ts
+++ b/src/mol-model-props/computed/interactions/contacts-builder.ts
@@ -46,7 +46,7 @@ namespace IntraContactsBuilder {
                     get: () => {
                         return elementsIndex || (elementsIndex = InteractionsIntraContacts.createElementsIndex(graph, features, elementsCount));
                     }
-                });
+                }) as any;
                 return contacts;
             }
         };
diff --git a/src/mol-plugin-state/manager/animation.ts b/src/mol-plugin-state/manager/animation.ts
index 81e7e845762e0bb037c621164dbc6b5b6de157f4..a87ecd417d9d4f84c7a31e0722b647169a9d6bb3 100644
--- a/src/mol-plugin-state/manager/animation.ts
+++ b/src/mol-plugin-state/manager/animation.ts
@@ -34,11 +34,11 @@ class PluginAnimationManager extends StatefulPluginComponent<PluginAnimationMana
     get animations() { return this._animations; }
 
     private triggerUpdate() {
-        this.events.updated.next();
+        this.events.updated.next(void 0);
     }
 
     private triggerApply() {
-        this.events.applied.next();
+        this.events.applied.next(void 0);
     }
 
     getParams(): PD.Params {
diff --git a/src/mol-plugin-state/manager/interactivity.ts b/src/mol-plugin-state/manager/interactivity.ts
index 5a7d5d144e56d390584c018c447167e9d47ff24f..ea7e6147914e63890a921508b35fc62e699e066f 100644
--- a/src/mol-plugin-state/manager/interactivity.ts
+++ b/src/mol-plugin-state/manager/interactivity.ts
@@ -52,7 +52,7 @@ class InteractivityManager extends StatefulPluginComponent<InteractivityManagerS
         this.updateState({ props: _new });
         this.lociSelects.setProps(_new);
         this.lociHighlights.setProps(_new);
-        this.events.propsUpdated.next();
+        this.events.propsUpdated.next(void 0);
     }
 
     constructor(readonly plugin: PluginContext, props: Partial<InteractivityManager.Props> = {}) {
diff --git a/src/mol-plugin-state/manager/snapshots.ts b/src/mol-plugin-state/manager/snapshots.ts
index 0509dba11b7f3627041abe092186759006b18dfa..7195947f4d4365af091f685591ec26fbfb6ca508 100644
--- a/src/mol-plugin-state/manager/snapshots.ts
+++ b/src/mol-plugin-state/manager/snapshots.ts
@@ -51,13 +51,13 @@ class PluginStateSnapshotManager extends StatefulPluginComponent<{
             current: this.state.current === id ? void 0 : this.state.current,
             entries: this.state.entries.delete(this.getIndex(e))
         });
-        this.events.changed.next();
+        this.events.changed.next(void 0);
     }
 
     add(e: PluginStateSnapshotManager.Entry) {
         this.entryMap.set(e.snapshot.id, e);
         this.updateState({ current: e.snapshot.id, entries: this.state.entries.push(e) });
-        this.events.changed.next();
+        this.events.changed.next(void 0);
     }
 
     replace(id: string, snapshot: PluginState.Snapshot) {
@@ -72,7 +72,7 @@ class PluginStateSnapshotManager extends StatefulPluginComponent<{
         });
         this.entryMap.set(snapshot.id, e);
         this.updateState({ current: e.snapshot.id, entries: this.state.entries.set(idx, e) });
-        this.events.changed.next();
+        this.events.changed.next(void 0);
     }
 
     move(id: string, dir: -1 | 1) {
@@ -91,21 +91,21 @@ class PluginStateSnapshotManager extends StatefulPluginComponent<{
         entries.set(from, f);
 
         this.updateState({ current: e.snapshot.id, entries: entries.asImmutable() });
-        this.events.changed.next();
+        this.events.changed.next(void 0);
     }
 
     clear() {
         if (this.state.entries.size === 0) return;
         this.entryMap.clear();
         this.updateState({ current: void 0, entries: List<PluginStateSnapshotManager.Entry>() });
-        this.events.changed.next();
+        this.events.changed.next(void 0);
     }
 
     setCurrent(id: string) {
         const e = this.getEntry(id);
         if (e) {
             this.updateState({ current: id as UUID });
-            this.events.changed.next();
+            this.events.changed.next(void 0);
         }
         return e && e.snapshot;
     }
@@ -152,7 +152,7 @@ class PluginStateSnapshotManager extends StatefulPluginComponent<{
             isPlaying: false,
             nextSnapshotDelayInMs: snapshot.playback ? snapshot.playback.nextSnapshotDelayInMs : PluginStateSnapshotManager.DefaultNextSnapshotDelayInMs
         });
-        this.events.changed.next();
+        this.events.changed.next(void 0);
         if (!current) return;
         const entry = this.getEntry(current);
         const next = entry && entry.snapshot;
@@ -288,7 +288,7 @@ class PluginStateSnapshotManager extends StatefulPluginComponent<{
                 this.next();
                 return;
             }
-            this.events.changed.next();
+            this.events.changed.next(void 0);
             const snapshot = e.snapshot;
             const delay = typeof snapshot.durationInMs !== 'undefined' ? snapshot.durationInMs : this.state.nextSnapshotDelayInMs;
             this.timeoutHandle = setTimeout(this.next, delay);
@@ -301,7 +301,7 @@ class PluginStateSnapshotManager extends StatefulPluginComponent<{
         this.updateState({ isPlaying: false });
         if (typeof this.timeoutHandle !== 'undefined') clearTimeout(this.timeoutHandle);
         this.timeoutHandle = void 0;
-        this.events.changed.next();
+        this.events.changed.next(void 0);
     }
 
     togglePlay() {
diff --git a/src/mol-plugin-state/manager/structure/component.ts b/src/mol-plugin-state/manager/structure/component.ts
index 82858b40948ce08a0110e6eccbed5e91bb3b1798..cfc61d3d95d089de7bd2f76b590b263fcbcc1a77 100644
--- a/src/mol-plugin-state/manager/structure/component.ts
+++ b/src/mol-plugin-state/manager/structure/component.ts
@@ -53,7 +53,7 @@ class StructureComponentManager extends StatefulPluginComponent<StructureCompone
     async setOptions(options: StructureComponentManager.Options) {
         const interactionChanged = options.interactions !== this.state.options.interactions;
         this.updateState({ options });
-        this.events.optionsUpdated.next();
+        this.events.optionsUpdated.next(void 0);
 
         const update = this.dataState.build();
 
diff --git a/src/mol-plugin-state/manager/structure/focus.ts b/src/mol-plugin-state/manager/structure/focus.ts
index 13753b6a0eac9d2b4db5a154b662e8d6de83b14c..836f50f77c5478e1307a49ba8d41bcf35af466b7 100644
--- a/src/mol-plugin-state/manager/structure/focus.ts
+++ b/src/mol-plugin-state/manager/structure/focus.ts
@@ -66,14 +66,14 @@ export class StructureFocusManager extends StatefulPluginComponent<StructureFocu
             // move to top, use new
             arrayRemoveAtInPlace(this.state.history, idx);
             this.state.history.unshift(entry);
-            this.events.historyUpdated.next();
+            this.events.historyUpdated.next(void 0);
             return;
         }
 
         this.state.history.unshift(entry);
         if (this.state.history.length > HISTORY_CAPACITY) this.state.history.pop();
 
-        this.events.historyUpdated.next();
+        this.events.historyUpdated.next(void 0);
     }
 
     set(entry: FocusEntry) {
@@ -156,7 +156,7 @@ export class StructureFocusManager extends StatefulPluginComponent<StructureFocu
             if (keep.length !== this.history.length) {
                 this.history.length = 0;
                 this.history.push(...keep);
-                this.events.historyUpdated.next();
+                this.events.historyUpdated.next(void 0);
             }
         });
 
diff --git a/src/mol-plugin-state/manager/structure/selection.ts b/src/mol-plugin-state/manager/structure/selection.ts
index cc291447b69fa99b6a85d6487db58251321bc7ee..a8e99b6d0f709cda0a278e8871ab4c72d5e7d531 100644
--- a/src/mol-plugin-state/manager/structure/selection.ts
+++ b/src/mol-plugin-state/manager/structure/selection.ts
@@ -175,7 +175,7 @@ export class StructureSelectionManager extends StatefulPluginComponent<Structure
             }
         }
 
-        this.events.additionsHistoryUpdated.next();
+        this.events.additionsHistoryUpdated.next(void 0);
     }
 
     private tryAddHistory(loci: StructureElement.Loci) {
@@ -194,7 +194,7 @@ export class StructureSelectionManager extends StatefulPluginComponent<Structure
             // move to top
             arrayRemoveAtInPlace(this.additionsHistory, idx);
             this.additionsHistory.unshift(entry);
-            this.events.additionsHistoryUpdated.next();
+            this.events.additionsHistoryUpdated.next(void 0);
             return;
         }
 
@@ -204,13 +204,13 @@ export class StructureSelectionManager extends StatefulPluginComponent<Structure
         this.additionsHistory.unshift({ id: UUID.create22(), loci, label });
         if (this.additionsHistory.length > HISTORY_CAPACITY) this.additionsHistory.pop();
 
-        this.events.additionsHistoryUpdated.next();
+        this.events.additionsHistoryUpdated.next(void 0);
     }
 
     private clearHistory() {
         if (this.state.additionsHistory.length !== 0) {
             this.state.additionsHistory = [];
-            this.events.additionsHistoryUpdated.next();
+            this.events.additionsHistoryUpdated.next(void 0);
         }
     }
 
@@ -225,7 +225,7 @@ export class StructureSelectionManager extends StatefulPluginComponent<Structure
             this.modifyHistory(e, 'remove');
         }
         if (historyEntryToRemove.length !== 0) {
-            this.events.additionsHistoryUpdated.next();
+            this.events.additionsHistoryUpdated.next(void 0);
         }
     }
 
@@ -239,7 +239,7 @@ export class StructureSelectionManager extends StatefulPluginComponent<Structure
                 this.referenceLoci = undefined;
             }
             this.state.stats = void 0;
-            this.events.changed.next();
+            this.events.changed.next(void 0);
         }
     }
 
@@ -276,7 +276,7 @@ export class StructureSelectionManager extends StatefulPluginComponent<Structure
                     changedHistory = true;
                 }
             }
-            if (changedHistory) this.events.additionsHistoryUpdated.next();
+            if (changedHistory) this.events.additionsHistoryUpdated.next(void 0);
         } else {
             // clear the selection for ref
             this.entries.set(ref, new SelectionEntry(StructureElement.Loci(structure, [])));
@@ -288,7 +288,7 @@ export class StructureSelectionManager extends StatefulPluginComponent<Structure
             this.clearHistoryForStructure(structure);
 
             this.state.stats = void 0;
-            this.events.changed.next();
+            this.events.changed.next(void 0);
         }
     }
 
@@ -305,8 +305,8 @@ export class StructureSelectionManager extends StatefulPluginComponent<Structure
         }
         this.referenceLoci = undefined;
         this.state.stats = void 0;
-        this.events.changed.next();
-        this.events.loci.clear.next();
+        this.events.changed.next(void 0);
+        this.events.loci.clear.next(void 0);
         this.clearHistory();
         return selections;
     }
@@ -426,7 +426,7 @@ export class StructureSelectionManager extends StatefulPluginComponent<Structure
 
         if (changed) {
             this.state.stats = void 0;
-            this.events.changed.next();
+            this.events.changed.next(void 0);
         }
     }
 
diff --git a/src/mol-plugin/behavior/static/camera.ts b/src/mol-plugin/behavior/static/camera.ts
index 7e74ad382317d1724af974b56c2be711b60c4a57..d0a0ec17e111bf145886a5ef0e5d1cb9924fcd68 100644
--- a/src/mol-plugin/behavior/static/camera.ts
+++ b/src/mol-plugin/behavior/static/camera.ts
@@ -28,6 +28,6 @@ export function SetSnapshot(ctx: PluginContext) {
 export function Focus(ctx: PluginContext) {
     PluginCommands.Camera.Focus.subscribe(ctx, ({ center, radius, durationMs }) => {
         ctx.managers.camera.focusSphere({ center, radius }, { durationMs });
-        ctx.events.canvas3d.settingsUpdated.next();
+        ctx.events.canvas3d.settingsUpdated.next(void 0);
     });
 }
\ No newline at end of file
diff --git a/src/mol-plugin/behavior/static/misc.ts b/src/mol-plugin/behavior/static/misc.ts
index 3fe93576e42aad7dc8fab2670e3f784e118c4865..8d0296c0efc4d49091ca34340ad8649a34e40ec0 100644
--- a/src/mol-plugin/behavior/static/misc.ts
+++ b/src/mol-plugin/behavior/static/misc.ts
@@ -16,13 +16,13 @@ export function registerDefault(ctx: PluginContext) {
 export function Canvas3DSetSettings(ctx: PluginContext) {
     PluginCommands.Canvas3D.ResetSettings.subscribe(ctx, () => {
         ctx.canvas3d?.setProps(DefaultCanvas3DParams);
-        ctx.events.canvas3d.settingsUpdated.next();
+        ctx.events.canvas3d.settingsUpdated.next(void 0);
     });
 
     PluginCommands.Canvas3D.SetSettings.subscribe(ctx, e => {
         if (!ctx.canvas3d) return;
 
         ctx.canvas3d?.setProps(e.settings);
-        ctx.events.canvas3d.settingsUpdated.next();
+        ctx.events.canvas3d.settingsUpdated.next(void 0);
     });
 }
diff --git a/src/mol-plugin/layout.ts b/src/mol-plugin/layout.ts
index 228201d294ecd4747445c3d48bdebf164b48fb12..b90fb951b4c71b3df5e28a985722fcb9f28c6e54 100644
--- a/src/mol-plugin/layout.ts
+++ b/src/mol-plugin/layout.ts
@@ -69,7 +69,7 @@ export class PluginLayout extends StatefulPluginComponent<PluginLayoutStateProps
         this.updateState(state);
         if (this.root && typeof state.isExpanded === 'boolean' && state.isExpanded !== prevExpanded) this.handleExpand();
 
-        this.events.updated.next();
+        this.events.updated.next(void 0);
     }
 
     root: HTMLElement | undefined;
diff --git a/src/mol-plugin/util/toast.ts b/src/mol-plugin/util/toast.ts
index 2a22e93904adcfb7de993ae0352cd4884f10bb4c..7aa3d02cbc1e7eee657ba49c44363060e31b3c63 100644
--- a/src/mol-plugin/util/toast.ts
+++ b/src/mol-plugin/util/toast.ts
@@ -64,7 +64,7 @@ export class PluginToastManager extends StatefulPluginComponent<{
             hide: () => this.hideId(id)
         };
 
-        if (this.updateState({ entries: entries.set(id, e) })) this.events.changed.next();
+        if (this.updateState({ entries: entries.set(id, e) })) this.events.changed.next(void 0);
     }
 
     private timeout(id: number, delay?: number) {
@@ -86,7 +86,7 @@ export class PluginToastManager extends StatefulPluginComponent<{
         if (!e) return;
         if (e.timeout !== void 0) clearTimeout(e.timeout);
         e.hide = <any>void 0;
-        if (this.updateState({ entries: this.state.entries.delete(e.id) })) this.events.changed.next();
+        if (this.updateState({ entries: this.state.entries.delete(e.id) })) this.events.changed.next(void 0);
     }
 
     constructor(plugin: PluginContext) {
diff --git a/src/mol-plugin/util/viewport-screenshot.ts b/src/mol-plugin/util/viewport-screenshot.ts
index b1454feb1e7ac3c5b87a182c1d266325045fe5ba..dcbc7ea57c4b4c662a59bb2bc3df0364f2f0c522 100644
--- a/src/mol-plugin/util/viewport-screenshot.ts
+++ b/src/mol-plugin/util/viewport-screenshot.ts
@@ -286,7 +286,7 @@ class ViewportScreenshotHelper extends PluginComponent {
         canvasCtx.putImageData(imageData, 0, 0);
         if (this.cropParams.auto) this.autocrop();
 
-        this.events.previewed.next();
+        this.events.previewed.next(void 0);
         return { canvas, width: w, height: h };
     }
 
diff --git a/src/mol-state/action/manager.ts b/src/mol-state/action/manager.ts
index a0c04ff63af39a7883ad47884f464ca212ab98b9..922e6195a098c9641e862ecfe170aff371de75d7 100644
--- a/src/mol-state/action/manager.ts
+++ b/src/mol-state/action/manager.ts
@@ -38,7 +38,7 @@ class StateActionManager {
             }
         }
 
-        this.events.added.next();
+        this.events.added.next(void 0);
 
         return this;
     }
@@ -62,7 +62,7 @@ class StateActionManager {
             if (xs.length === 0) this.fromTypeIndex.delete(t.type);
         }
 
-        this.events.removed.next();
+        this.events.removed.next(void 0);
 
         return this;
     }
diff --git a/src/mol-util/download.ts b/src/mol-util/download.ts
index eb65b4a6f5737200063702bde49815fb415b1862..0d2887827f738d28e2a1edee969c86eb6022fae7 100644
--- a/src/mol-util/download.ts
+++ b/src/mol-util/download.ts
@@ -39,9 +39,9 @@ export function download (data: Blob | string, downloadName = 'download') {
             setTimeout(() => URL.revokeObjectURL(a.href), 4E4); // 40s
             setTimeout(() => click(a));
         }
-    } else if (typeof navigator !== 'undefined' && navigator.msSaveOrOpenBlob) {
+    } else if (typeof navigator !== 'undefined' && (navigator as any).msSaveOrOpenBlob) {
         // native saveAs in IE 10+
-        navigator.msSaveOrOpenBlob(data, downloadName);
+        (navigator as any).msSaveOrOpenBlob(data, downloadName);
     } else {
         const ua = window.navigator.userAgent;
         const isSafari = /Safari/i.test(ua);
diff --git a/src/mol-util/input/input-observer.ts b/src/mol-util/input/input-observer.ts
index 58b61096b62510578e67bc4f040c3693ff934364..8579c7240ad05d16a1711776ee8a3ea6bbf5f52a 100644
--- a/src/mol-util/input/input-observer.ts
+++ b/src/mol-util/input/input-observer.ts
@@ -558,7 +558,7 @@ namespace InputObserver {
         }
 
         function endDrag() {
-            interactionEnd.next();
+            interactionEnd.next(void 0);
         }
 
         function onPointerDown(ev: PointerEvent) {
@@ -671,16 +671,16 @@ namespace InputObserver {
 
         function onMouseEnter(ev: Event) {
             isInside = true;
-            enter.next();
+            enter.next(void 0);
         }
 
         function onMouseLeave(ev: Event) {
             isInside = false;
-            leave.next();
+            leave.next(void 0);
         }
 
         function onResize(ev: Event) {
-            resize.next();
+            resize.next({});
         }
 
         function insideBounds(pos: Vec2) {