@hawsen-the-first/interactiv 0.0.2 → 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -1
- package/dist/src/appBuilder.d.ts +32 -0
- package/dist/src/appBuilder.d.ts.map +1 -1
- package/dist/src/appBuilder.js +93 -0
- package/dist/src/eventBus.d.ts +1 -2
- package/dist/src/eventBus.d.ts.map +1 -1
- package/dist/src/eventBus.js +4 -16
- package/dist/src/navigationManager.d.ts +4 -0
- package/dist/src/navigationManager.d.ts.map +1 -1
- package/dist/src/navigationManager.js +46 -7
- package/dist/src/screensaverManager.d.ts +13 -0
- package/dist/src/screensaverManager.d.ts.map +1 -1
- package/dist/src/screensaverManager.js +51 -1
- package/dist/src/transitionOverlay.d.ts +96 -0
- package/dist/src/transitionOverlay.d.ts.map +1 -0
- package/dist/src/transitionOverlay.js +328 -0
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -15,6 +15,7 @@ import { Logger } from "./utils/logger";
|
|
|
15
15
|
import { useAnimations, AnimationManager } from "./src/animationBus";
|
|
16
16
|
import { configureLogger } from "./src/logger";
|
|
17
17
|
import { GarbageCollector, createGarbageCollector, type GarbageCollectionStats } from "./src/garbageCollector";
|
|
18
|
-
|
|
19
|
-
export
|
|
18
|
+
import { TransitionOverlay, transitionWithOverlay, type TransitionOverlayConfig, type TransitionRequestPayload } from "./src/transitionOverlay";
|
|
19
|
+
export { createOrchestrator, EventOrchestrator, EventBus, AppBuilder, Page, View, Component, NavigationManager, ScreensaverManager, SettingsManager, EventManager, AnimationManager, stateManager, getGlobalState, setGlobalState, subscribeToGlobalState, useGlobalStateExternal, useAnimations, ExternalStateManager, ComponentStateManager, GarbageCollector, createGarbageCollector, TransitionOverlay, transitionWithOverlay, css, html, Logger, configureLogger, };
|
|
20
|
+
export type { PointerEventData, DragCallbacks, HoverCallbacks, SwipeCallbacks, StateSubscription, ScreensaverConfig, SettingsConfig, PageProps, ViewProps, ComponentProps, GarbageCollectionStats, TransitionOverlayConfig, TransitionRequestPayload, };
|
|
20
21
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACrE,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AACjF,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAC9D,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EACL,YAAY,EACZ,cAAc,EACd,cAAc,EACd,sBAAsB,EACtB,sBAAsB,EACtB,oBAAoB,EACpB,qBAAqB,EACtB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EACV,gBAAgB,EAChB,aAAa,EACb,cAAc,EACd,cAAc,EACf,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAC5D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,KAAK,EAAE,SAAS,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxE,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,0BAA0B,CAAC;AACrD,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AACxC,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACrE,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EACL,gBAAgB,EAChB,sBAAsB,EACtB,KAAK,sBAAsB,EAC5B,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACrE,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AACjF,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAC9D,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EACL,YAAY,EACZ,cAAc,EACd,cAAc,EACd,sBAAsB,EACtB,sBAAsB,EACtB,oBAAoB,EACpB,qBAAqB,EACtB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EACV,gBAAgB,EAChB,aAAa,EACb,cAAc,EACd,cAAc,EACf,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAC5D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,KAAK,EAAE,SAAS,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxE,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,0BAA0B,CAAC;AACrD,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AACxC,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACrE,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EACL,gBAAgB,EAChB,sBAAsB,EACtB,KAAK,sBAAsB,EAC5B,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,iBAAiB,EACjB,qBAAqB,EACrB,KAAK,uBAAuB,EAC5B,KAAK,wBAAwB,EAC9B,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EACL,kBAAkB,EAClB,iBAAiB,EACjB,QAAQ,EACR,UAAU,EACV,IAAI,EACJ,IAAI,EACJ,SAAS,EACT,iBAAiB,EACjB,kBAAkB,EAClB,eAAe,EACf,YAAY,EACZ,gBAAgB,EAEhB,YAAY,EACZ,cAAc,EACd,cAAc,EACd,sBAAsB,EACtB,sBAAsB,EACtB,aAAa,EACb,oBAAoB,EACpB,qBAAqB,EAErB,gBAAgB,EAChB,sBAAsB,EAEtB,iBAAiB,EACjB,qBAAqB,EACrB,GAAG,EACH,IAAI,EACJ,MAAM,EACN,eAAe,GAChB,CAAC;AAEF,YAAY,EACV,gBAAgB,EAChB,aAAa,EACb,cAAc,EACd,cAAc,EACd,iBAAiB,EACjB,iBAAiB,EACjB,cAAc,EACd,SAAS,EACT,SAAS,EACT,cAAc,EACd,sBAAsB,EACtB,uBAAuB,EACvB,wBAAwB,GACzB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -10,12 +10,15 @@ import { Logger } from "./utils/logger";
|
|
|
10
10
|
import { useAnimations, AnimationManager } from "./src/animationBus";
|
|
11
11
|
import { configureLogger } from "./src/logger";
|
|
12
12
|
import { GarbageCollector, createGarbageCollector, } from "./src/garbageCollector";
|
|
13
|
+
import { TransitionOverlay, transitionWithOverlay, } from "./src/transitionOverlay";
|
|
13
14
|
5;
|
|
14
15
|
export { createOrchestrator, EventOrchestrator, EventBus, AppBuilder, Page, View, Component, NavigationManager, ScreensaverManager, SettingsManager, EventManager, AnimationManager,
|
|
15
16
|
// External State Management
|
|
16
17
|
stateManager, getGlobalState, setGlobalState, subscribeToGlobalState, useGlobalStateExternal, useAnimations, ExternalStateManager, ComponentStateManager,
|
|
17
18
|
// Garbage Collection
|
|
18
|
-
GarbageCollector, createGarbageCollector,
|
|
19
|
+
GarbageCollector, createGarbageCollector,
|
|
20
|
+
// Transition Overlay System
|
|
21
|
+
TransitionOverlay, transitionWithOverlay, css, html, Logger, configureLogger, };
|
|
19
22
|
// Named exports for direct import
|
|
20
23
|
// export {
|
|
21
24
|
// stateManager,
|
package/dist/src/appBuilder.d.ts
CHANGED
|
@@ -5,6 +5,7 @@ import { EventManager } from "./eventManager";
|
|
|
5
5
|
import { ComponentStateManager } from "./stateManager";
|
|
6
6
|
import type { PointerEventData, DragCallbacks, HoverCallbacks, SwipeCallbacks } from "./eventManager";
|
|
7
7
|
import type { RenderOptions } from "./types";
|
|
8
|
+
import { TransitionOverlay, type TransitionOverlayConfig } from "./transitionOverlay";
|
|
8
9
|
declare abstract class RenderableComponent {
|
|
9
10
|
componentId: string;
|
|
10
11
|
state: any;
|
|
@@ -139,11 +140,42 @@ declare class AppBuilder extends RenderableComponent {
|
|
|
139
140
|
}
|
|
140
141
|
declare class Page extends RenderableComponent {
|
|
141
142
|
private views;
|
|
143
|
+
private transitionOverlay;
|
|
144
|
+
private transitionBus;
|
|
142
145
|
constructor(id: string, orchestrator: EventOrchestrator, bubbleChanges?: boolean, customTemplate?: string, customStyles?: string);
|
|
143
146
|
protected defineTemplate(): void;
|
|
144
147
|
protected defineStyles(): void;
|
|
145
148
|
addView(view: View): void;
|
|
146
149
|
removeView(viewId: string): void;
|
|
150
|
+
/**
|
|
151
|
+
* Enable transition overlay for this page
|
|
152
|
+
*
|
|
153
|
+
* Creates a full-screen overlay that fades in/out to hide content changes during state updates.
|
|
154
|
+
* Once enabled, components can request transitions via the "page-transition-overlay" event bus.
|
|
155
|
+
*
|
|
156
|
+
* @param config - Configuration for the overlay appearance and timing
|
|
157
|
+
*/
|
|
158
|
+
useTransitionOverlay(config: TransitionOverlayConfig): void;
|
|
159
|
+
/**
|
|
160
|
+
* Execute a callback wrapped in the transition overlay lifecycle
|
|
161
|
+
*
|
|
162
|
+
* This is a convenience method for direct Page-level access to the overlay.
|
|
163
|
+
* For deeply nested components, prefer using the standalone `transitionWithOverlay` utility
|
|
164
|
+
* or emitting to the "page-transition-overlay" event bus.
|
|
165
|
+
*
|
|
166
|
+
* @param callback - Function to execute while overlay is opaque (state changes happen here)
|
|
167
|
+
* @returns Promise that resolves after the full transition completes
|
|
168
|
+
* @throws Error if useTransitionOverlay() hasn't been called
|
|
169
|
+
*/
|
|
170
|
+
transitionWithOverlay(callback: () => void | Promise<void>): Promise<void>;
|
|
171
|
+
/**
|
|
172
|
+
* Check if this page has a transition overlay enabled
|
|
173
|
+
*/
|
|
174
|
+
hasTransitionOverlay(): boolean;
|
|
175
|
+
/**
|
|
176
|
+
* Get the TransitionOverlay instance for this page (for NavigationManager integration)
|
|
177
|
+
*/
|
|
178
|
+
getTransitionOverlay(): TransitionOverlay | null;
|
|
147
179
|
/**
|
|
148
180
|
* Add a screensaver page with the specified configuration.
|
|
149
181
|
* Pass `null` for screensaverPage when using `screensaverViewBehavior: "returnHome"` mode,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"appBuilder.d.ts","sourceRoot":"","sources":["../../src/appBuilder.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAEzD,OAAO,EAEL,KAAK,iBAAiB,EACvB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAmB,KAAK,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACzE,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AACvD,OAAO,KAAK,EACV,gBAAgB,EAChB,aAAa,EACb,cAAc,EACd,cAAc,EACf,MAAM,gBAAgB,CAAC;AACxB,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"appBuilder.d.ts","sourceRoot":"","sources":["../../src/appBuilder.ts"],"names":[],"mappings":"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"}
|
package/dist/src/appBuilder.js
CHANGED
|
@@ -6,6 +6,7 @@ import { SettingsManager } from "./settingsManager";
|
|
|
6
6
|
import { EventManager } from "./eventManager";
|
|
7
7
|
import { ComponentStateManager } from "./stateManager";
|
|
8
8
|
import { logger } from "./logger";
|
|
9
|
+
import { TransitionOverlay, stateChangesToCallback, } from "./transitionOverlay";
|
|
9
10
|
class RenderableComponent {
|
|
10
11
|
componentId;
|
|
11
12
|
state;
|
|
@@ -538,6 +539,8 @@ class AppBuilder extends RenderableComponent {
|
|
|
538
539
|
// Page - Contains Views
|
|
539
540
|
class Page extends RenderableComponent {
|
|
540
541
|
views = [];
|
|
542
|
+
transitionOverlay = null;
|
|
543
|
+
transitionBus = null;
|
|
541
544
|
constructor(id, orchestrator, bubbleChanges = true, customTemplate, customStyles) {
|
|
542
545
|
super(id, orchestrator, bubbleChanges);
|
|
543
546
|
// Set custom template/styles before initial render if provided
|
|
@@ -647,6 +650,96 @@ class Page extends RenderableComponent {
|
|
|
647
650
|
this.removeChild(viewId);
|
|
648
651
|
}
|
|
649
652
|
}
|
|
653
|
+
/**
|
|
654
|
+
* Enable transition overlay for this page
|
|
655
|
+
*
|
|
656
|
+
* Creates a full-screen overlay that fades in/out to hide content changes during state updates.
|
|
657
|
+
* Once enabled, components can request transitions via the "page-transition-overlay" event bus.
|
|
658
|
+
*
|
|
659
|
+
* @param config - Configuration for the overlay appearance and timing
|
|
660
|
+
*/
|
|
661
|
+
useTransitionOverlay(config) {
|
|
662
|
+
if (this.transitionOverlay) {
|
|
663
|
+
logger.warn(`Page ${this.componentId} already has a transition overlay configured`);
|
|
664
|
+
return;
|
|
665
|
+
}
|
|
666
|
+
// Create the transition overlay
|
|
667
|
+
this.transitionOverlay = new TransitionOverlay(config, this.shadowRoot);
|
|
668
|
+
// Register the event bus for transition requests
|
|
669
|
+
this.transitionBus = this.orchestrator.registerEventBus("page-transition-overlay");
|
|
670
|
+
// Listen for transition requests
|
|
671
|
+
this.transitionBus.on("request-transition", async (e) => {
|
|
672
|
+
const payload = e.detail;
|
|
673
|
+
try {
|
|
674
|
+
// Build the callback from state changes or use provided callback
|
|
675
|
+
let callback;
|
|
676
|
+
if (payload.callback) {
|
|
677
|
+
// Direct callback provided (from standalone utility)
|
|
678
|
+
callback = payload.callback;
|
|
679
|
+
}
|
|
680
|
+
else if (payload.stateChanges) {
|
|
681
|
+
// State changes array provided (from consumer usage)
|
|
682
|
+
callback = async () => {
|
|
683
|
+
stateChangesToCallback(payload.stateChanges)();
|
|
684
|
+
// Execute afterStateChange if provided
|
|
685
|
+
if (payload.afterStateChange) {
|
|
686
|
+
await Promise.resolve(payload.afterStateChange());
|
|
687
|
+
}
|
|
688
|
+
};
|
|
689
|
+
}
|
|
690
|
+
else {
|
|
691
|
+
throw new Error("Transition request must include either 'callback' or 'stateChanges'");
|
|
692
|
+
}
|
|
693
|
+
// Execute the transition with config overrides
|
|
694
|
+
await this.transitionOverlay.executeTransition(callback, {
|
|
695
|
+
fadeInDuration: payload.fadeInDuration,
|
|
696
|
+
holdDuration: payload.holdDuration,
|
|
697
|
+
fadeOutDuration: payload.fadeOutDuration,
|
|
698
|
+
});
|
|
699
|
+
// Resolve the promise if provided (from standalone utility)
|
|
700
|
+
if (payload._resolve) {
|
|
701
|
+
payload._resolve();
|
|
702
|
+
}
|
|
703
|
+
}
|
|
704
|
+
catch (error) {
|
|
705
|
+
logger.error("Transition overlay error:", error);
|
|
706
|
+
// Reject the promise if provided (from standalone utility)
|
|
707
|
+
if (payload._reject) {
|
|
708
|
+
payload._reject(error);
|
|
709
|
+
}
|
|
710
|
+
}
|
|
711
|
+
});
|
|
712
|
+
logger.trace(`Transition overlay enabled for page ${this.componentId}`);
|
|
713
|
+
}
|
|
714
|
+
/**
|
|
715
|
+
* Execute a callback wrapped in the transition overlay lifecycle
|
|
716
|
+
*
|
|
717
|
+
* This is a convenience method for direct Page-level access to the overlay.
|
|
718
|
+
* For deeply nested components, prefer using the standalone `transitionWithOverlay` utility
|
|
719
|
+
* or emitting to the "page-transition-overlay" event bus.
|
|
720
|
+
*
|
|
721
|
+
* @param callback - Function to execute while overlay is opaque (state changes happen here)
|
|
722
|
+
* @returns Promise that resolves after the full transition completes
|
|
723
|
+
* @throws Error if useTransitionOverlay() hasn't been called
|
|
724
|
+
*/
|
|
725
|
+
async transitionWithOverlay(callback) {
|
|
726
|
+
if (!this.transitionOverlay) {
|
|
727
|
+
throw new Error(`Page ${this.componentId} does not have a transition overlay. Call useTransitionOverlay() first.`);
|
|
728
|
+
}
|
|
729
|
+
return this.transitionOverlay.executeTransition(callback);
|
|
730
|
+
}
|
|
731
|
+
/**
|
|
732
|
+
* Check if this page has a transition overlay enabled
|
|
733
|
+
*/
|
|
734
|
+
hasTransitionOverlay() {
|
|
735
|
+
return this.transitionOverlay !== null;
|
|
736
|
+
}
|
|
737
|
+
/**
|
|
738
|
+
* Get the TransitionOverlay instance for this page (for NavigationManager integration)
|
|
739
|
+
*/
|
|
740
|
+
getTransitionOverlay() {
|
|
741
|
+
return this.transitionOverlay;
|
|
742
|
+
}
|
|
650
743
|
/**
|
|
651
744
|
* Add a screensaver page with the specified configuration.
|
|
652
745
|
* Pass `null` for screensaverPage when using `screensaverViewBehavior: "returnHome"` mode,
|
package/dist/src/eventBus.d.ts
CHANGED
|
@@ -18,8 +18,7 @@ export declare class EventBus<DetailType = any> {
|
|
|
18
18
|
* Destroy this event bus and clean up all listeners
|
|
19
19
|
*/
|
|
20
20
|
destroy(): void;
|
|
21
|
-
emit(type: string, detail?: DetailType): boolean
|
|
22
|
-
private validateEventDispatch;
|
|
21
|
+
emit(type: string, detail?: DetailType): boolean;
|
|
23
22
|
}
|
|
24
23
|
export declare class EventOrchestrator {
|
|
25
24
|
private eventBuses;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"eventBus.d.ts","sourceRoot":"","sources":["../../src/eventBus.ts"],"names":[],"mappings":"AAMA,qBAAa,QAAQ,CAAC,UAAU,GAAG,GAAG;IACpC,OAAO,CAAC,WAAW,CAAc;IACjC,OAAO,CAAC,eAAe,CAA6B;IACpD,OAAO,CAAC,EAAE,CAAS;gBACP,WAAW,SAAc;IAIrC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,WAAW,CAAC,UAAU,CAAC,KAAK,IAAI;IAiBnE,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,WAAW,CAAC,UAAU,CAAC,KAAK,IAAI;IAiBrE,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAmB1B;;OAEG;IACH,SAAS,IAAI,IAAI;IAQjB;;OAEG;IACH,gBAAgB,IAAI,MAAM;IAI1B;;OAEG;IACH,OAAO,IAAI,IAAI;IASf,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,UAAU;
|
|
1
|
+
{"version":3,"file":"eventBus.d.ts","sourceRoot":"","sources":["../../src/eventBus.ts"],"names":[],"mappings":"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"}
|
package/dist/src/eventBus.js
CHANGED
|
@@ -86,24 +86,12 @@ export class EventBus {
|
|
|
86
86
|
log.trace(`Event Bus ${this.id} destroyed`);
|
|
87
87
|
}
|
|
88
88
|
emit(type, detail) {
|
|
89
|
-
|
|
90
|
-
this.validateEventDispatch(type);
|
|
91
|
-
return this.eventTarget.dispatchEvent(new CustomEvent(type, { detail }));
|
|
92
|
-
}
|
|
93
|
-
catch (error) {
|
|
94
|
-
log.error(error.message, error);
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
// private validateNewListener(type: string): void {
|
|
98
|
-
// // Allow multiple listeners for the same event type
|
|
99
|
-
// // This validation is too restrictive for our use case
|
|
100
|
-
// // Components may need to register multiple listeners for the same event
|
|
101
|
-
// return;
|
|
102
|
-
// }
|
|
103
|
-
validateEventDispatch(type) {
|
|
89
|
+
// Check if there are any listeners before dispatching
|
|
104
90
|
if (this.activeListeners.filter((l) => l.eventName === type).length === 0) {
|
|
105
|
-
|
|
91
|
+
log.trace(`Event Bus [${this.id}]: No listeners registered for event "${type}", skipping dispatch.`);
|
|
92
|
+
return true; // Return true to indicate the event was "handled" (just not dispatched)
|
|
106
93
|
}
|
|
94
|
+
return this.eventTarget.dispatchEvent(new CustomEvent(type, { detail }));
|
|
107
95
|
}
|
|
108
96
|
}
|
|
109
97
|
export class EventOrchestrator {
|
|
@@ -66,6 +66,10 @@ export declare class NavigationManager {
|
|
|
66
66
|
private performPageNavigationInternal;
|
|
67
67
|
private performViewNavigationInternal;
|
|
68
68
|
private performPageTransition;
|
|
69
|
+
/**
|
|
70
|
+
* Perform an immediate view swap (no animation) - used when transition overlay is handling the fade
|
|
71
|
+
*/
|
|
72
|
+
private performViewSwapImmediate;
|
|
69
73
|
private performViewTransition;
|
|
70
74
|
private animateOut;
|
|
71
75
|
private animateIn;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"navigationManager.d.ts","sourceRoot":"","sources":["../../src/navigationManager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAY,iBAAiB,EAAE,MAAM,YAAY,CAAC;AACzD,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAgB,KAAK,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAKtE,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,OAAO,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,QAAQ,CAAC;IAC9D,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,MAAM,CAAC;IAC7C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,eAAe;IAC9B,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,eAAe,EAAE,OAAO,CAAC;CAC1B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAkC;IACzD,OAAO,CAAC,MAAM,CAAC,WAAW,CAAkB;IAE5C,OAAO,CAAC,QAAQ,CAAW;IAC3B,OAAO,CAAC,YAAY,CAAoB;IACxC,OAAO,CAAC,KAAK,CAAgC;IAC7C,OAAO,CAAC,KAAK,CAAgC;IAC7C,OAAO,CAAC,kBAAkB,CAA2B;IACrD,OAAO,CAAC,wBAAwB,CAA2C;IAE3E;;;OAGG;WACW,WAAW,IAAI,iBAAiB,GAAG,IAAI;gBAIzC,YAAY,EAAE,iBAAiB;IA4B3C,OAAO,CAAC,qBAAqB;IAa7B,OAAO,CAAC,mBAAmB;IAsBpB,YAAY,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI;IAa9B,YAAY,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI;IAQrC,OAAO,CAAC,kBAAkB;IAM1B,OAAO,CAAC,kBAAkB;IAMb,cAAc,CACzB,MAAM,EAAE,MAAM,EACd,MAAM,GAAE,gBAAmC,EAC3C,QAAQ,GAAE,MAAoB,GAC7B,OAAO,CAAC,IAAI,CAAC;IAYH,cAAc,CACzB,MAAM,EAAE,MAAM,EACd,MAAM,GAAE,gBAAmC,EAC3C,QAAQ,GAAE,MAAoB,GAC7B,OAAO,CAAC,IAAI,CAAC;YAYF,6BAA6B;YA6B7B,6BAA6B;
|
|
1
|
+
{"version":3,"file":"navigationManager.d.ts","sourceRoot":"","sources":["../../src/navigationManager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAY,iBAAiB,EAAE,MAAM,YAAY,CAAC;AACzD,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAgB,KAAK,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAKtE,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,OAAO,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,QAAQ,CAAC;IAC9D,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,MAAM,CAAC;IAC7C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,eAAe;IAC9B,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,eAAe,EAAE,OAAO,CAAC;CAC1B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAkC;IACzD,OAAO,CAAC,MAAM,CAAC,WAAW,CAAkB;IAE5C,OAAO,CAAC,QAAQ,CAAW;IAC3B,OAAO,CAAC,YAAY,CAAoB;IACxC,OAAO,CAAC,KAAK,CAAgC;IAC7C,OAAO,CAAC,KAAK,CAAgC;IAC7C,OAAO,CAAC,kBAAkB,CAA2B;IACrD,OAAO,CAAC,wBAAwB,CAA2C;IAE3E;;;OAGG;WACW,WAAW,IAAI,iBAAiB,GAAG,IAAI;gBAIzC,YAAY,EAAE,iBAAiB;IA4B3C,OAAO,CAAC,qBAAqB;IAa7B,OAAO,CAAC,mBAAmB;IAsBpB,YAAY,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI;IAa9B,YAAY,CAAC,IAAI,EAAE,IAAI,GAAG,IAAI;IAQrC,OAAO,CAAC,kBAAkB;IAM1B,OAAO,CAAC,kBAAkB;IAMb,cAAc,CACzB,MAAM,EAAE,MAAM,EACd,MAAM,GAAE,gBAAmC,EAC3C,QAAQ,GAAE,MAAoB,GAC7B,OAAO,CAAC,IAAI,CAAC;IAYH,cAAc,CACzB,MAAM,EAAE,MAAM,EACd,MAAM,GAAE,gBAAmC,EAC3C,QAAQ,GAAE,MAAoB,GAC7B,OAAO,CAAC,IAAI,CAAC;YAYF,6BAA6B;YA6B7B,6BAA6B;YAwD7B,qBAAqB;IAmBnC;;OAEG;YACW,wBAAwB;YAiBxB,qBAAqB;YAqBrB,UAAU;YAuEV,SAAS;IA2FvB,OAAO,CAAC,yBAAyB;IAkBjC,OAAO,CAAC,qBAAqB;IAwB7B,OAAO,CAAC,QAAQ;IAUhB,OAAO,CAAC,QAAQ;IAchB,OAAO,CAAC,QAAQ;IAgBhB,OAAO,CAAC,QAAQ;IAUhB,OAAO,CAAC,YAAY;IAQb,gBAAgB,IAAI,MAAM,GAAG,IAAI;IAIjC,gBAAgB,IAAI,MAAM,GAAG,IAAI;IAIjC,eAAe,IAAI,OAAO;IAI1B,kBAAkB,IAAI,MAAM,EAAE;IAI9B,kBAAkB,IAAI,MAAM,EAAE;IAK9B,sBAAsB,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,GAAG,iBAAiB;IAIpF,sBAAsB,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,GAAG,iBAAiB;IAIpF,0BAA0B,CAAC,QAAQ,EAAE,CAAC,eAAe,EAAE,OAAO,KAAK,IAAI,GAAG,iBAAiB;IAIlG;;;OAGG;IACI,0BAA0B,IAAI,IAAI;IAezC;;OAEG;IACI,wBAAwB,IAAI,MAAM;IAIzC;;;;;;OAMG;IACI,OAAO,IAAI,IAAI;CAoBvB"}
|
|
@@ -181,13 +181,35 @@ export class NavigationManager {
|
|
|
181
181
|
log.trace(`Starting navigation from ${previousViewId} to ${viewId}`);
|
|
182
182
|
stateManager.set("navigation.isTransitioning", true);
|
|
183
183
|
try {
|
|
184
|
-
|
|
185
|
-
stateManager.
|
|
186
|
-
this.
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
184
|
+
// Check if current page has a transition overlay
|
|
185
|
+
const currentPageId = stateManager.get("navigation.currentPageId");
|
|
186
|
+
const currentPage = currentPageId ? this.pages.get(currentPageId) : null;
|
|
187
|
+
const hasOverlay = currentPage && currentPage.hasTransitionOverlay();
|
|
188
|
+
if (hasOverlay) {
|
|
189
|
+
// Use the overlay to wrap the view transition
|
|
190
|
+
log.trace(`Using transition overlay for view navigation to ${viewId}`);
|
|
191
|
+
const overlay = currentPage.getTransitionOverlay();
|
|
192
|
+
await overlay.executeTransition(async () => {
|
|
193
|
+
// Perform the view swap while overlay is opaque
|
|
194
|
+
await this.performViewSwapImmediate(viewId, previousViewId);
|
|
195
|
+
stateManager.set("navigation.currentViewId", viewId);
|
|
196
|
+
});
|
|
197
|
+
this.eventBus.emit("view-changed", {
|
|
198
|
+
newViewId: viewId,
|
|
199
|
+
previousViewId,
|
|
200
|
+
});
|
|
201
|
+
log.trace(`Navigation to ${viewId} completed successfully with overlay`);
|
|
202
|
+
}
|
|
203
|
+
else {
|
|
204
|
+
// No overlay - use standard transition
|
|
205
|
+
await this.performViewTransition(viewId, config);
|
|
206
|
+
stateManager.set("navigation.currentViewId", viewId);
|
|
207
|
+
this.eventBus.emit("view-changed", {
|
|
208
|
+
newViewId: viewId,
|
|
209
|
+
previousViewId,
|
|
210
|
+
});
|
|
211
|
+
log.trace(`Navigation to ${viewId} completed successfully`);
|
|
212
|
+
}
|
|
191
213
|
}
|
|
192
214
|
catch (error) {
|
|
193
215
|
log.error(`Navigation to ${viewId} failed:`, error);
|
|
@@ -211,6 +233,23 @@ export class NavigationManager {
|
|
|
211
233
|
}
|
|
212
234
|
await this.animateIn(targetPage.getHostElement(), normalizedConfig);
|
|
213
235
|
}
|
|
236
|
+
/**
|
|
237
|
+
* Perform an immediate view swap (no animation) - used when transition overlay is handling the fade
|
|
238
|
+
*/
|
|
239
|
+
async performViewSwapImmediate(targetViewId, currentViewId) {
|
|
240
|
+
const currentView = currentViewId ? this.views.get(currentViewId) : null;
|
|
241
|
+
const targetView = this.views.get(targetViewId);
|
|
242
|
+
// Hide current view immediately
|
|
243
|
+
if (currentView) {
|
|
244
|
+
this.hideView(currentViewId);
|
|
245
|
+
}
|
|
246
|
+
// Show target view immediately (no animation since overlay handles the fade)
|
|
247
|
+
this.showView(targetViewId, false);
|
|
248
|
+
const element = targetView.getHostElement();
|
|
249
|
+
element.style.opacity = "1";
|
|
250
|
+
element.style.visibility = "visible";
|
|
251
|
+
element.style.transform = "none";
|
|
252
|
+
}
|
|
214
253
|
async performViewTransition(targetViewId, config) {
|
|
215
254
|
const currentViewId = stateManager.get("navigation.currentViewId");
|
|
216
255
|
const currentView = currentViewId ? this.views.get(currentViewId) : null;
|
|
@@ -32,7 +32,10 @@ export declare class ScreensaverManager {
|
|
|
32
32
|
private lastScreensaverViewId;
|
|
33
33
|
private lastActivityResetTime;
|
|
34
34
|
private globalListeners;
|
|
35
|
+
private interactionShieldActive;
|
|
36
|
+
private shieldRemovalTimer;
|
|
35
37
|
private readonly DEBOUNCE_INTERVAL;
|
|
38
|
+
private readonly SHIELD_DURATION;
|
|
36
39
|
private readonly DEFAULT_ACTIVITY_EVENTS;
|
|
37
40
|
constructor(orchestrator: EventOrchestrator, navigationManager: NavigationManager);
|
|
38
41
|
private initializeGlobalState;
|
|
@@ -69,5 +72,15 @@ export declare class ScreensaverManager {
|
|
|
69
72
|
private checkAndPerformReboot;
|
|
70
73
|
private startRebootCheckInterval;
|
|
71
74
|
private stopRebootCheckInterval;
|
|
75
|
+
/**
|
|
76
|
+
* Activates the interaction shield to block follow-up events from the same gesture
|
|
77
|
+
* that dismissed the screensaver. This prevents touch events from bleeding through
|
|
78
|
+
* to elements on the home page.
|
|
79
|
+
*/
|
|
80
|
+
private activateInteractionShield;
|
|
81
|
+
/**
|
|
82
|
+
* Deactivates the interaction shield, allowing normal event processing to resume.
|
|
83
|
+
*/
|
|
84
|
+
private deactivateInteractionShield;
|
|
72
85
|
}
|
|
73
86
|
//# sourceMappingURL=screensaverManager.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"screensaverManager.d.ts","sourceRoot":"","sources":["../../src/screensaverManager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAY,iBAAiB,EAAE,MAAM,YAAY,CAAC;AACzD,OAAO,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AACpC,OAAO,EAAE,iBAAiB,EAAE,KAAK,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAM/E,MAAM,WAAW,iBAAiB;IAChC,cAAc,EAAE,MAAM,CAAC;IACvB,IAAI,CAAC,EAAE,IAAI,CAAC;IACZ,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,uBAAuB,CAAC,EAAE,SAAS,GAAG,UAAU,GAAG,QAAQ,GAAG,YAAY,CAAC;IAC3E,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IACpC,YAAY,CAAC,EAAE,OAAO,GAAG,QAAQ,CAAC;IAClC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC5B,gBAAgB,CAAC,EAAE,MAAM,IAAI,CAAC;IAC9B,kBAAkB,CAAC,EAAE,MAAM,IAAI,CAAC;IAChC,eAAe,CAAC,EAAE,MAAM,OAAO,CAAC;IAChC,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,cAAc,CAAC,EAAE,MAAM,IAAI,CAAC;CAC7B;AAED,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,QAAQ,CAAW;IAC3B,OAAO,CAAC,YAAY,CAAoB;IACxC,OAAO,CAAC,iBAAiB,CAAoB;IAC7C,OAAO,CAAC,MAAM,CAAkC;IAChD,OAAO,CAAC,aAAa,CAAuB;IAC5C,OAAO,CAAC,mBAAmB,CAAuB;IAClD,OAAO,CAAC,mBAAmB,CAAkB;IAC7C,OAAO,CAAC,gBAAgB,CAAuB;IAC/C,OAAO,CAAC,gBAAgB,CAAuB;IAC/C,OAAO,CAAC,qBAAqB,CAAuB;IACpD,OAAO,CAAC,qBAAqB,CAAuB;IACpD,OAAO,CAAC,eAAe,CAIf;IAGR,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAQ;IAG1C,OAAO,CAAC,QAAQ,CAAC,uBAAuB,CAStC;gBAEU,YAAY,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,iBAAiB;IASjF,OAAO,CAAC,qBAAqB;IAkB7B,OAAO,CAAC,mBAAmB;IAyCpB,mBAAmB,CAAC,MAAM,EAAE,iBAAiB,GAAG,IAAI;IAyC3D,OAAO,CAAC,gBAAgB;IAIxB,OAAO,CAAC,cAAc;IAkCtB,OAAO,CAAC,4BAA4B;
|
|
1
|
+
{"version":3,"file":"screensaverManager.d.ts","sourceRoot":"","sources":["../../src/screensaverManager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAY,iBAAiB,EAAE,MAAM,YAAY,CAAC;AACzD,OAAO,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AACpC,OAAO,EAAE,iBAAiB,EAAE,KAAK,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAM/E,MAAM,WAAW,iBAAiB;IAChC,cAAc,EAAE,MAAM,CAAC;IACvB,IAAI,CAAC,EAAE,IAAI,CAAC;IACZ,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,uBAAuB,CAAC,EAAE,SAAS,GAAG,UAAU,GAAG,QAAQ,GAAG,YAAY,CAAC;IAC3E,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IACpC,YAAY,CAAC,EAAE,OAAO,GAAG,QAAQ,CAAC;IAClC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC5B,gBAAgB,CAAC,EAAE,MAAM,IAAI,CAAC;IAC9B,kBAAkB,CAAC,EAAE,MAAM,IAAI,CAAC;IAChC,eAAe,CAAC,EAAE,MAAM,OAAO,CAAC;IAChC,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,cAAc,CAAC,EAAE,MAAM,IAAI,CAAC;CAC7B;AAED,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,QAAQ,CAAW;IAC3B,OAAO,CAAC,YAAY,CAAoB;IACxC,OAAO,CAAC,iBAAiB,CAAoB;IAC7C,OAAO,CAAC,MAAM,CAAkC;IAChD,OAAO,CAAC,aAAa,CAAuB;IAC5C,OAAO,CAAC,mBAAmB,CAAuB;IAClD,OAAO,CAAC,mBAAmB,CAAkB;IAC7C,OAAO,CAAC,gBAAgB,CAAuB;IAC/C,OAAO,CAAC,gBAAgB,CAAuB;IAC/C,OAAO,CAAC,qBAAqB,CAAuB;IACpD,OAAO,CAAC,qBAAqB,CAAuB;IACpD,OAAO,CAAC,eAAe,CAIf;IAGR,OAAO,CAAC,uBAAuB,CAAkB;IACjD,OAAO,CAAC,kBAAkB,CAAuB;IAGjD,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAQ;IAG1C,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAO;IAGvC,OAAO,CAAC,QAAQ,CAAC,uBAAuB,CAStC;gBAEU,YAAY,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,iBAAiB;IASjF,OAAO,CAAC,qBAAqB;IAkB7B,OAAO,CAAC,mBAAmB;IAyCpB,mBAAmB,CAAC,MAAM,EAAE,iBAAiB,GAAG,IAAI;IAyC3D,OAAO,CAAC,gBAAgB;IAIxB,OAAO,CAAC,cAAc;IAkCtB,OAAO,CAAC,4BAA4B;IAiEpC,OAAO,CAAC,oBAAoB;IAgB5B,OAAO,CAAC,kBAAkB;IAe1B,OAAO,CAAC,kBAAkB;IAO1B,OAAO,CAAC,kBAAkB;YAOZ,mBAAmB;IA6DjC;;;;OAIG;YACW,kBAAkB;IAkDhC,OAAO,CAAC,wBAAwB;YAclB,qBAAqB;YAsDrB,qBAAqB;IAI5B,QAAQ,IAAI,OAAO;IAInB,gBAAgB,IAAI,iBAAiB,GAAG,IAAI;IAI5C,mBAAmB,IAAI,MAAM,GAAG,IAAI;IAIpC,mBAAmB,IAAI,MAAM,GAAG,IAAI;IAIpC,wBAAwB,IAAI,MAAM,GAAG,IAAI;IAKzC,aAAa,IAAI,IAAI;IAKrB,eAAe,IAAI,IAAI;IAIvB,UAAU,IAAI,IAAI;IAMzB,OAAO,CAAC,OAAO;IAeR,OAAO,IAAI,IAAI;IAUtB,OAAO,CAAC,uBAAuB;IAc/B,OAAO,CAAC,qBAAqB;IAc7B,OAAO,CAAC,wBAAwB;IAchC,OAAO,CAAC,uBAAuB;IAS/B;;;;OAIG;IACH,OAAO,CAAC,yBAAyB;IAgBjC;;OAEG;IACH,OAAO,CAAC,2BAA2B;CASpC"}
|
|
@@ -14,8 +14,13 @@ export class ScreensaverManager {
|
|
|
14
14
|
lastScreensaverViewId = null;
|
|
15
15
|
lastActivityResetTime = null;
|
|
16
16
|
globalListeners = [];
|
|
17
|
+
// Interaction shield state
|
|
18
|
+
interactionShieldActive = false;
|
|
19
|
+
shieldRemovalTimer = null;
|
|
17
20
|
// Debounce interval for activity timer resets (in milliseconds)
|
|
18
21
|
DEBOUNCE_INTERVAL = 1000;
|
|
22
|
+
// Shield duration to block follow-up events from the same gesture (in milliseconds)
|
|
23
|
+
SHIELD_DURATION = 400;
|
|
19
24
|
// Default activity events to monitor
|
|
20
25
|
DEFAULT_ACTIVITY_EVENTS = [
|
|
21
26
|
"mousemove",
|
|
@@ -156,6 +161,13 @@ export class ScreensaverManager {
|
|
|
156
161
|
if (!this.config)
|
|
157
162
|
return;
|
|
158
163
|
const activityHandler = (event) => {
|
|
164
|
+
// Block all events if interaction shield is active
|
|
165
|
+
if (this.interactionShieldActive) {
|
|
166
|
+
event.stopPropagation();
|
|
167
|
+
event.preventDefault();
|
|
168
|
+
log.trace(`Interaction shield blocked ${event.type} event`);
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
159
171
|
// Check if event should be ignored based on excludeSelectors
|
|
160
172
|
if (this.shouldIgnoreActivity(event)) {
|
|
161
173
|
return;
|
|
@@ -174,9 +186,14 @@ export class ScreensaverManager {
|
|
|
174
186
|
}
|
|
175
187
|
};
|
|
176
188
|
// Add listeners to document for global coverage
|
|
189
|
+
// Use non-passive listeners for click and touch events to allow preventDefault()
|
|
177
190
|
this.config.activityEvents.forEach((eventType) => {
|
|
178
191
|
const listener = activityHandler.bind(this);
|
|
179
|
-
|
|
192
|
+
const usePassive = !["click", "touchstart", "touchend"].includes(eventType);
|
|
193
|
+
document.addEventListener(eventType, listener, {
|
|
194
|
+
passive: usePassive,
|
|
195
|
+
capture: true // Use capture phase to intercept events before they reach targets
|
|
196
|
+
});
|
|
180
197
|
this.globalListeners.push({
|
|
181
198
|
element: document,
|
|
182
199
|
type: eventType,
|
|
@@ -356,6 +373,8 @@ export class ScreensaverManager {
|
|
|
356
373
|
if (!this.config || !this.isScreensaverActive)
|
|
357
374
|
return;
|
|
358
375
|
log.trace(`Exiting screensaver with '${this.config.exitBehavior}' behavior`);
|
|
376
|
+
// Activate interaction shield to block follow-up events from the same gesture
|
|
377
|
+
this.activateInteractionShield();
|
|
359
378
|
// Stop the reboot check interval
|
|
360
379
|
this.stopRebootCheckInterval();
|
|
361
380
|
if (this.config.deactivateCallback)
|
|
@@ -432,6 +451,7 @@ export class ScreensaverManager {
|
|
|
432
451
|
cleanup() {
|
|
433
452
|
this.clearActivityTimer();
|
|
434
453
|
this.stopRebootCheckInterval();
|
|
454
|
+
this.deactivateInteractionShield();
|
|
435
455
|
// Remove all global event listeners
|
|
436
456
|
this.globalListeners.forEach(({ element, type, listener }) => {
|
|
437
457
|
element.removeEventListener(type, listener);
|
|
@@ -490,4 +510,34 @@ export class ScreensaverManager {
|
|
|
490
510
|
log.trace("Reboot check interval stopped");
|
|
491
511
|
}
|
|
492
512
|
}
|
|
513
|
+
// Interaction shield methods
|
|
514
|
+
/**
|
|
515
|
+
* Activates the interaction shield to block follow-up events from the same gesture
|
|
516
|
+
* that dismissed the screensaver. This prevents touch events from bleeding through
|
|
517
|
+
* to elements on the home page.
|
|
518
|
+
*/
|
|
519
|
+
activateInteractionShield() {
|
|
520
|
+
// Clear any existing shield timer
|
|
521
|
+
if (this.shieldRemovalTimer !== null) {
|
|
522
|
+
clearTimeout(this.shieldRemovalTimer);
|
|
523
|
+
this.shieldRemovalTimer = null;
|
|
524
|
+
}
|
|
525
|
+
this.interactionShieldActive = true;
|
|
526
|
+
log.trace("Interaction shield activated");
|
|
527
|
+
// Automatically deactivate shield after the gesture completes
|
|
528
|
+
this.shieldRemovalTimer = window.setTimeout(() => {
|
|
529
|
+
this.deactivateInteractionShield();
|
|
530
|
+
}, this.SHIELD_DURATION);
|
|
531
|
+
}
|
|
532
|
+
/**
|
|
533
|
+
* Deactivates the interaction shield, allowing normal event processing to resume.
|
|
534
|
+
*/
|
|
535
|
+
deactivateInteractionShield() {
|
|
536
|
+
if (this.shieldRemovalTimer !== null) {
|
|
537
|
+
clearTimeout(this.shieldRemovalTimer);
|
|
538
|
+
this.shieldRemovalTimer = null;
|
|
539
|
+
}
|
|
540
|
+
this.interactionShieldActive = false;
|
|
541
|
+
log.trace("Interaction shield deactivated");
|
|
542
|
+
}
|
|
493
543
|
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { EventOrchestrator } from "./eventBus";
|
|
2
|
+
export interface TransitionOverlayConfig {
|
|
3
|
+
backgroundColor?: string;
|
|
4
|
+
fadeInDuration?: number;
|
|
5
|
+
holdDuration?: number;
|
|
6
|
+
fadeOutDuration?: number;
|
|
7
|
+
zIndex?: number;
|
|
8
|
+
}
|
|
9
|
+
export interface TransitionRequestPayload {
|
|
10
|
+
stateChanges?: Array<{
|
|
11
|
+
key: string;
|
|
12
|
+
value: any;
|
|
13
|
+
}>;
|
|
14
|
+
afterStateChange?: () => void | Promise<void>;
|
|
15
|
+
fadeInDuration?: number;
|
|
16
|
+
holdDuration?: number;
|
|
17
|
+
fadeOutDuration?: number;
|
|
18
|
+
}
|
|
19
|
+
type TransitionPhase = "idle" | "fade-in" | "hold" | "fade-out";
|
|
20
|
+
/**
|
|
21
|
+
* TransitionOverlay - Manages visual overlay transitions for seamless content updates
|
|
22
|
+
*
|
|
23
|
+
* This class provides a fade-to-opaque overlay that hides content changes during state updates.
|
|
24
|
+
*
|
|
25
|
+
* **Concurrency Strategy:**
|
|
26
|
+
* - If a transition is in the **fade-in or hold phase**, incoming requests queue their callbacks
|
|
27
|
+
* to be batched into the current cycle's hold phase
|
|
28
|
+
* - If a transition is in the **fade-out phase**, incoming requests start a new transition cycle
|
|
29
|
+
* after the current one completes
|
|
30
|
+
*
|
|
31
|
+
* This ensures smooth transitions without jarring interruptions or visible content changes.
|
|
32
|
+
*/
|
|
33
|
+
export declare class TransitionOverlay {
|
|
34
|
+
private config;
|
|
35
|
+
private shadowRoot;
|
|
36
|
+
private overlayElement;
|
|
37
|
+
private currentPhase;
|
|
38
|
+
private queuedCallbacks;
|
|
39
|
+
private queuedRequests;
|
|
40
|
+
private activeTransitionPromise;
|
|
41
|
+
constructor(config: TransitionOverlayConfig, shadowRoot: ShadowRoot);
|
|
42
|
+
private injectOverlayElement;
|
|
43
|
+
/**
|
|
44
|
+
* Execute a transition with the overlay lifecycle
|
|
45
|
+
*
|
|
46
|
+
* @param callback - Function to execute while overlay is opaque (state changes happen here)
|
|
47
|
+
* @param configOverrides - Optional per-request config overrides
|
|
48
|
+
* @returns Promise that resolves after the full transition completes
|
|
49
|
+
*/
|
|
50
|
+
executeTransition(callback: () => void | Promise<void>, configOverrides?: Partial<TransitionOverlayConfig>): Promise<void>;
|
|
51
|
+
private handleConcurrentRequest;
|
|
52
|
+
private performTransition;
|
|
53
|
+
private fadeIn;
|
|
54
|
+
private executeCallbacks;
|
|
55
|
+
private fadeOut;
|
|
56
|
+
private processQueuedRequests;
|
|
57
|
+
/**
|
|
58
|
+
* Update the overlay configuration
|
|
59
|
+
*/
|
|
60
|
+
updateConfig(config: Partial<TransitionOverlayConfig>): void;
|
|
61
|
+
/**
|
|
62
|
+
* Get the current transition phase
|
|
63
|
+
*/
|
|
64
|
+
getPhase(): TransitionPhase;
|
|
65
|
+
/**
|
|
66
|
+
* Check if a transition is currently active
|
|
67
|
+
*/
|
|
68
|
+
isTransitioning(): boolean;
|
|
69
|
+
/**
|
|
70
|
+
* Clean up the overlay element and resources
|
|
71
|
+
*/
|
|
72
|
+
destroy(): void;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Standalone utility for requesting overlay transitions via event bus
|
|
76
|
+
*
|
|
77
|
+
* This is the recommended way for components to request transitions, as it:
|
|
78
|
+
* 1. Works from anywhere in the component tree
|
|
79
|
+
* 2. Gracefully falls back to direct execution if no overlay is available
|
|
80
|
+
* 3. Supports state changes via the standardized event format
|
|
81
|
+
*
|
|
82
|
+
* @param orchestrator - The EventOrchestrator instance
|
|
83
|
+
* @param callback - Function to execute during the transition (while overlay is opaque)
|
|
84
|
+
* @param config - Optional per-request config overrides
|
|
85
|
+
* @returns Promise that resolves after the transition completes
|
|
86
|
+
*/
|
|
87
|
+
export declare function transitionWithOverlay(orchestrator: EventOrchestrator, callback: () => void | Promise<void>, config?: Partial<TransitionOverlayConfig>): Promise<void>;
|
|
88
|
+
/**
|
|
89
|
+
* Helper to convert state changes array to callback function
|
|
90
|
+
*/
|
|
91
|
+
export declare function stateChangesToCallback(stateChanges: Array<{
|
|
92
|
+
key: string;
|
|
93
|
+
value: any;
|
|
94
|
+
}>): () => void;
|
|
95
|
+
export {};
|
|
96
|
+
//# sourceMappingURL=transitionOverlay.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transitionOverlay.d.ts","sourceRoot":"","sources":["../../src/transitionOverlay.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAM/C,MAAM,WAAW,uBAAuB;IACtC,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,wBAAwB;IACvC,YAAY,CAAC,EAAE,KAAK,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,GAAG,CAAA;KAAE,CAAC,CAAC;IAClD,gBAAgB,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9C,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AASD,KAAK,eAAe,GAAG,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,UAAU,CAAC;AAEhE;;;;;;;;;;;;GAYG;AACH,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,MAAM,CAAoC;IAClD,OAAO,CAAC,UAAU,CAAa;IAC/B,OAAO,CAAC,cAAc,CAA+B;IACrD,OAAO,CAAC,YAAY,CAA2B;IAC/C,OAAO,CAAC,eAAe,CAAyC;IAChE,OAAO,CAAC,cAAc,CAAiC;IACvD,OAAO,CAAC,uBAAuB,CAA8B;gBAEjD,MAAM,EAAE,uBAAuB,EAAE,UAAU,EAAE,UAAU;IAYnE,OAAO,CAAC,oBAAoB;IA8B5B;;;;;;OAMG;IACU,iBAAiB,CAC5B,QAAQ,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,EACpC,eAAe,CAAC,EAAE,OAAO,CAAC,uBAAuB,CAAC,GACjD,OAAO,CAAC,IAAI,CAAC;IAiBhB,OAAO,CAAC,uBAAuB;YAwBjB,iBAAiB;IAmC/B,OAAO,CAAC,MAAM;YAoDA,gBAAgB;IAsB9B,OAAO,CAAC,OAAO;IAmDf,OAAO,CAAC,qBAAqB;IAW7B;;OAEG;IACI,YAAY,CAAC,MAAM,EAAE,OAAO,CAAC,uBAAuB,CAAC,GAAG,IAAI;IAgBnE;;OAEG;IACI,QAAQ,IAAI,eAAe;IAIlC;;OAEG;IACI,eAAe,IAAI,OAAO;IAIjC;;OAEG;IACI,OAAO,IAAI,IAAI;CAUvB;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,qBAAqB,CACzC,YAAY,EAAE,iBAAiB,EAC/B,QAAQ,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,EACpC,MAAM,CAAC,EAAE,OAAO,CAAC,uBAAuB,CAAC,GACxC,OAAO,CAAC,IAAI,CAAC,CAwBf;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CACpC,YAAY,EAAE,KAAK,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,GAAG,CAAA;CAAE,CAAC,GAC/C,MAAM,IAAI,CAMZ"}
|
|
@@ -0,0 +1,328 @@
|
|
|
1
|
+
import { setGlobalState } from "./stateManager";
|
|
2
|
+
import { logger } from "./logger";
|
|
3
|
+
const log = logger;
|
|
4
|
+
/**
|
|
5
|
+
* TransitionOverlay - Manages visual overlay transitions for seamless content updates
|
|
6
|
+
*
|
|
7
|
+
* This class provides a fade-to-opaque overlay that hides content changes during state updates.
|
|
8
|
+
*
|
|
9
|
+
* **Concurrency Strategy:**
|
|
10
|
+
* - If a transition is in the **fade-in or hold phase**, incoming requests queue their callbacks
|
|
11
|
+
* to be batched into the current cycle's hold phase
|
|
12
|
+
* - If a transition is in the **fade-out phase**, incoming requests start a new transition cycle
|
|
13
|
+
* after the current one completes
|
|
14
|
+
*
|
|
15
|
+
* This ensures smooth transitions without jarring interruptions or visible content changes.
|
|
16
|
+
*/
|
|
17
|
+
export class TransitionOverlay {
|
|
18
|
+
config;
|
|
19
|
+
shadowRoot;
|
|
20
|
+
overlayElement = null;
|
|
21
|
+
currentPhase = "idle";
|
|
22
|
+
queuedCallbacks = [];
|
|
23
|
+
queuedRequests = [];
|
|
24
|
+
activeTransitionPromise = null;
|
|
25
|
+
constructor(config, shadowRoot) {
|
|
26
|
+
this.config = {
|
|
27
|
+
backgroundColor: config.backgroundColor ?? "#000",
|
|
28
|
+
fadeInDuration: config.fadeInDuration ?? 200,
|
|
29
|
+
holdDuration: config.holdDuration ?? 100,
|
|
30
|
+
fadeOutDuration: config.fadeOutDuration ?? 200,
|
|
31
|
+
zIndex: config.zIndex ?? 100,
|
|
32
|
+
};
|
|
33
|
+
this.shadowRoot = shadowRoot;
|
|
34
|
+
this.injectOverlayElement();
|
|
35
|
+
}
|
|
36
|
+
injectOverlayElement() {
|
|
37
|
+
this.overlayElement = document.createElement("div");
|
|
38
|
+
this.overlayElement.className = "transition-overlay";
|
|
39
|
+
this.overlayElement.style.cssText = `
|
|
40
|
+
position: absolute;
|
|
41
|
+
inset: 0;
|
|
42
|
+
background-color: ${this.config.backgroundColor};
|
|
43
|
+
opacity: 0;
|
|
44
|
+
pointer-events: none;
|
|
45
|
+
z-index: ${this.config.zIndex};
|
|
46
|
+
will-change: opacity;
|
|
47
|
+
transition: opacity ${this.config.fadeInDuration}ms ease-in-out;
|
|
48
|
+
`;
|
|
49
|
+
// Append to the shadow root or to .page if it exists
|
|
50
|
+
const pageElement = this.shadowRoot.querySelector(".page");
|
|
51
|
+
const container = pageElement || this.shadowRoot;
|
|
52
|
+
// Ensure the container has relative positioning for absolute overlay
|
|
53
|
+
if (container instanceof HTMLElement) {
|
|
54
|
+
const currentPosition = window.getComputedStyle(container).position;
|
|
55
|
+
if (currentPosition === "static") {
|
|
56
|
+
container.style.position = "relative";
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
container.appendChild(this.overlayElement);
|
|
60
|
+
log.trace("TransitionOverlay element injected into shadow DOM");
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Execute a transition with the overlay lifecycle
|
|
64
|
+
*
|
|
65
|
+
* @param callback - Function to execute while overlay is opaque (state changes happen here)
|
|
66
|
+
* @param configOverrides - Optional per-request config overrides
|
|
67
|
+
* @returns Promise that resolves after the full transition completes
|
|
68
|
+
*/
|
|
69
|
+
async executeTransition(callback, configOverrides) {
|
|
70
|
+
// Merge config overrides
|
|
71
|
+
const effectiveConfig = {
|
|
72
|
+
...this.config,
|
|
73
|
+
...configOverrides,
|
|
74
|
+
};
|
|
75
|
+
// Handle concurrency
|
|
76
|
+
if (this.currentPhase !== "idle") {
|
|
77
|
+
return this.handleConcurrentRequest(callback, effectiveConfig);
|
|
78
|
+
}
|
|
79
|
+
// Start new transition
|
|
80
|
+
this.activeTransitionPromise = this.performTransition(callback, effectiveConfig);
|
|
81
|
+
return this.activeTransitionPromise;
|
|
82
|
+
}
|
|
83
|
+
handleConcurrentRequest(callback, config) {
|
|
84
|
+
return new Promise((resolve, reject) => {
|
|
85
|
+
// If we're in fade-in or hold, batch this callback into the current cycle
|
|
86
|
+
if (this.currentPhase === "fade-in" || this.currentPhase === "hold") {
|
|
87
|
+
log.trace("Batching callback into current transition cycle", {
|
|
88
|
+
currentPhase: this.currentPhase
|
|
89
|
+
});
|
|
90
|
+
this.queuedCallbacks.push(callback);
|
|
91
|
+
// Resolve when the current transition completes
|
|
92
|
+
this.activeTransitionPromise?.then(resolve).catch(reject);
|
|
93
|
+
}
|
|
94
|
+
// If we're in fade-out, queue for the next cycle
|
|
95
|
+
else if (this.currentPhase === "fade-out") {
|
|
96
|
+
log.trace("Queueing request for next transition cycle", {
|
|
97
|
+
currentPhase: this.currentPhase
|
|
98
|
+
});
|
|
99
|
+
this.queuedRequests.push({ callback, config, resolve, reject });
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
async performTransition(callback, config) {
|
|
104
|
+
if (!this.overlayElement) {
|
|
105
|
+
throw new Error("Overlay element not initialized");
|
|
106
|
+
}
|
|
107
|
+
try {
|
|
108
|
+
// Phase 1: Fade in
|
|
109
|
+
this.currentPhase = "fade-in";
|
|
110
|
+
await this.fadeIn(config.fadeInDuration);
|
|
111
|
+
// Phase 2: Hold & execute callbacks
|
|
112
|
+
this.currentPhase = "hold";
|
|
113
|
+
await this.executeCallbacks(callback, config.holdDuration);
|
|
114
|
+
// Phase 3: Fade out
|
|
115
|
+
this.currentPhase = "fade-out";
|
|
116
|
+
await this.fadeOut(config.fadeOutDuration);
|
|
117
|
+
// Back to idle
|
|
118
|
+
this.currentPhase = "idle";
|
|
119
|
+
// Process any queued requests
|
|
120
|
+
this.processQueuedRequests();
|
|
121
|
+
}
|
|
122
|
+
catch (error) {
|
|
123
|
+
log.error("Transition error:", error);
|
|
124
|
+
this.currentPhase = "idle";
|
|
125
|
+
this.queuedCallbacks = [];
|
|
126
|
+
throw error;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
fadeIn(duration) {
|
|
130
|
+
if (!this.overlayElement)
|
|
131
|
+
return Promise.resolve();
|
|
132
|
+
return new Promise((resolve) => {
|
|
133
|
+
const element = this.overlayElement;
|
|
134
|
+
// Update transition duration
|
|
135
|
+
element.style.transition = `opacity ${duration}ms ease-in-out`;
|
|
136
|
+
// Enable pointer events to block interaction
|
|
137
|
+
element.style.pointerEvents = "all";
|
|
138
|
+
let transitionEndFired = false;
|
|
139
|
+
let fallbackTimerId = null;
|
|
140
|
+
const cleanup = () => {
|
|
141
|
+
if (transitionEndFired)
|
|
142
|
+
return;
|
|
143
|
+
transitionEndFired = true;
|
|
144
|
+
element.removeEventListener("transitionend", transitionEndHandler);
|
|
145
|
+
if (fallbackTimerId !== null) {
|
|
146
|
+
clearTimeout(fallbackTimerId);
|
|
147
|
+
fallbackTimerId = null;
|
|
148
|
+
}
|
|
149
|
+
log.trace("Overlay fade-in complete");
|
|
150
|
+
resolve();
|
|
151
|
+
};
|
|
152
|
+
const transitionEndHandler = (e) => {
|
|
153
|
+
// Only respond to opacity transitions on this element
|
|
154
|
+
if (e.target === element && e.propertyName === "opacity") {
|
|
155
|
+
cleanup();
|
|
156
|
+
}
|
|
157
|
+
};
|
|
158
|
+
element.addEventListener("transitionend", transitionEndHandler);
|
|
159
|
+
// Trigger fade-in by setting opacity to 1
|
|
160
|
+
// Use requestAnimationFrame to ensure CSS transition is applied
|
|
161
|
+
requestAnimationFrame(() => {
|
|
162
|
+
element.style.opacity = "1";
|
|
163
|
+
});
|
|
164
|
+
// Fallback timeout
|
|
165
|
+
fallbackTimerId = window.setTimeout(() => {
|
|
166
|
+
log.trace("Overlay fade-in fallback timeout triggered");
|
|
167
|
+
cleanup();
|
|
168
|
+
}, duration + 50);
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
async executeCallbacks(callback, holdDuration) {
|
|
172
|
+
// Execute the main callback
|
|
173
|
+
await Promise.resolve(callback());
|
|
174
|
+
// Execute any batched callbacks
|
|
175
|
+
if (this.queuedCallbacks.length > 0) {
|
|
176
|
+
log.trace(`Executing ${this.queuedCallbacks.length} batched callbacks`);
|
|
177
|
+
for (const queuedCallback of this.queuedCallbacks) {
|
|
178
|
+
await Promise.resolve(queuedCallback());
|
|
179
|
+
}
|
|
180
|
+
this.queuedCallbacks = [];
|
|
181
|
+
}
|
|
182
|
+
// Hold duration
|
|
183
|
+
if (holdDuration > 0) {
|
|
184
|
+
await new Promise(resolve => setTimeout(resolve, holdDuration));
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
fadeOut(duration) {
|
|
188
|
+
if (!this.overlayElement)
|
|
189
|
+
return Promise.resolve();
|
|
190
|
+
return new Promise((resolve) => {
|
|
191
|
+
const element = this.overlayElement;
|
|
192
|
+
// Update transition duration
|
|
193
|
+
element.style.transition = `opacity ${duration}ms ease-in-out`;
|
|
194
|
+
let transitionEndFired = false;
|
|
195
|
+
let fallbackTimerId = null;
|
|
196
|
+
const cleanup = () => {
|
|
197
|
+
if (transitionEndFired)
|
|
198
|
+
return;
|
|
199
|
+
transitionEndFired = true;
|
|
200
|
+
element.removeEventListener("transitionend", transitionEndHandler);
|
|
201
|
+
if (fallbackTimerId !== null) {
|
|
202
|
+
clearTimeout(fallbackTimerId);
|
|
203
|
+
fallbackTimerId = null;
|
|
204
|
+
}
|
|
205
|
+
// Disable pointer events after fade-out
|
|
206
|
+
element.style.pointerEvents = "none";
|
|
207
|
+
log.trace("Overlay fade-out complete");
|
|
208
|
+
resolve();
|
|
209
|
+
};
|
|
210
|
+
const transitionEndHandler = (e) => {
|
|
211
|
+
// Only respond to opacity transitions on this element
|
|
212
|
+
if (e.target === element && e.propertyName === "opacity") {
|
|
213
|
+
cleanup();
|
|
214
|
+
}
|
|
215
|
+
};
|
|
216
|
+
element.addEventListener("transitionend", transitionEndHandler);
|
|
217
|
+
// Trigger fade-out by setting opacity to 0
|
|
218
|
+
requestAnimationFrame(() => {
|
|
219
|
+
element.style.opacity = "0";
|
|
220
|
+
});
|
|
221
|
+
// Fallback timeout
|
|
222
|
+
fallbackTimerId = window.setTimeout(() => {
|
|
223
|
+
log.trace("Overlay fade-out fallback timeout triggered");
|
|
224
|
+
cleanup();
|
|
225
|
+
}, duration + 50);
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
processQueuedRequests() {
|
|
229
|
+
if (this.queuedRequests.length > 0) {
|
|
230
|
+
log.trace(`Processing ${this.queuedRequests.length} queued transition requests`);
|
|
231
|
+
const request = this.queuedRequests.shift();
|
|
232
|
+
this.performTransition(request.callback, request.config)
|
|
233
|
+
.then(request.resolve)
|
|
234
|
+
.catch(request.reject);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Update the overlay configuration
|
|
239
|
+
*/
|
|
240
|
+
updateConfig(config) {
|
|
241
|
+
this.config = {
|
|
242
|
+
...this.config,
|
|
243
|
+
...config,
|
|
244
|
+
};
|
|
245
|
+
if (this.overlayElement) {
|
|
246
|
+
if (config.backgroundColor) {
|
|
247
|
+
this.overlayElement.style.backgroundColor = config.backgroundColor;
|
|
248
|
+
}
|
|
249
|
+
if (config.zIndex !== undefined) {
|
|
250
|
+
this.overlayElement.style.zIndex = String(config.zIndex);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* Get the current transition phase
|
|
256
|
+
*/
|
|
257
|
+
getPhase() {
|
|
258
|
+
return this.currentPhase;
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* Check if a transition is currently active
|
|
262
|
+
*/
|
|
263
|
+
isTransitioning() {
|
|
264
|
+
return this.currentPhase !== "idle";
|
|
265
|
+
}
|
|
266
|
+
/**
|
|
267
|
+
* Clean up the overlay element and resources
|
|
268
|
+
*/
|
|
269
|
+
destroy() {
|
|
270
|
+
if (this.overlayElement && this.overlayElement.parentNode) {
|
|
271
|
+
this.overlayElement.parentNode.removeChild(this.overlayElement);
|
|
272
|
+
}
|
|
273
|
+
this.overlayElement = null;
|
|
274
|
+
this.queuedCallbacks = [];
|
|
275
|
+
this.queuedRequests = [];
|
|
276
|
+
this.currentPhase = "idle";
|
|
277
|
+
log.trace("TransitionOverlay destroyed");
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* Standalone utility for requesting overlay transitions via event bus
|
|
282
|
+
*
|
|
283
|
+
* This is the recommended way for components to request transitions, as it:
|
|
284
|
+
* 1. Works from anywhere in the component tree
|
|
285
|
+
* 2. Gracefully falls back to direct execution if no overlay is available
|
|
286
|
+
* 3. Supports state changes via the standardized event format
|
|
287
|
+
*
|
|
288
|
+
* @param orchestrator - The EventOrchestrator instance
|
|
289
|
+
* @param callback - Function to execute during the transition (while overlay is opaque)
|
|
290
|
+
* @param config - Optional per-request config overrides
|
|
291
|
+
* @returns Promise that resolves after the transition completes
|
|
292
|
+
*/
|
|
293
|
+
export async function transitionWithOverlay(orchestrator, callback, config) {
|
|
294
|
+
const transitionBus = orchestrator.getEventBus("page-transition-overlay");
|
|
295
|
+
if (transitionBus) {
|
|
296
|
+
// Wrap in a promise that resolves when the transition completes
|
|
297
|
+
return new Promise((resolve, reject) => {
|
|
298
|
+
try {
|
|
299
|
+
transitionBus.emit("request-transition", {
|
|
300
|
+
callback,
|
|
301
|
+
...config,
|
|
302
|
+
_resolve: resolve,
|
|
303
|
+
_reject: reject,
|
|
304
|
+
});
|
|
305
|
+
}
|
|
306
|
+
catch (error) {
|
|
307
|
+
// If the emit fails (no listeners), fall back to direct execution
|
|
308
|
+
log.warn("No transition overlay available, executing callback directly");
|
|
309
|
+
Promise.resolve(callback()).then(resolve).catch(reject);
|
|
310
|
+
}
|
|
311
|
+
});
|
|
312
|
+
}
|
|
313
|
+
else {
|
|
314
|
+
// Fallback: no overlay available, execute directly
|
|
315
|
+
log.trace("No transition overlay bus found, executing callback directly");
|
|
316
|
+
await Promise.resolve(callback());
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
/**
|
|
320
|
+
* Helper to convert state changes array to callback function
|
|
321
|
+
*/
|
|
322
|
+
export function stateChangesToCallback(stateChanges) {
|
|
323
|
+
return () => {
|
|
324
|
+
stateChanges.forEach(({ key, value }) => {
|
|
325
|
+
setGlobalState(key, value);
|
|
326
|
+
});
|
|
327
|
+
};
|
|
328
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hawsen-the-first/interactiv",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.4",
|
|
4
4
|
"description": "A TypeScript framework for building interactive applications with event management, state management, navigation, and screensaver functionality",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.js",
|