Repository: arkivanov/Decompose
Pull request #670 (2024-03-08 10:37:53)

Improved component context API for better custom component contexts


Patch:
diff --git a/decompose/api/android/decompose.api b/decompose/api/android/decompose.api
index 3db91a65..897d7e49 100644
--- a/decompose/api/android/decompose.api
+++ b/decompose/api/android/decompose.api
@@ -33,12 +33,20 @@ public final class com/arkivanov/decompose/Child$Destroyed : com/arkivanov/decom
 	public fun toString ()Ljava/lang/String;
 }
 
-public abstract interface class com/arkivanov/decompose/ComponentContext : com/arkivanov/essenty/backhandler/BackHandlerOwner, com/arkivanov/essenty/instancekeeper/InstanceKeeperOwner, com/arkivanov/essenty/lifecycle/LifecycleOwner, com/arkivanov/essenty/statekeeper/StateKeeperOwner {
+public abstract interface class com/arkivanov/decompose/ComponentContext : com/arkivanov/decompose/GenericComponentContext {
 }
 
 public final class com/arkivanov/decompose/ComponentContextExtKt {
-	public static final fun childContext (Lcom/arkivanov/decompose/ComponentContext;Ljava/lang/String;Lcom/arkivanov/essenty/lifecycle/Lifecycle;)Lcom/arkivanov/decompose/ComponentContext;
-	public static synthetic fun childContext$default (Lcom/arkivanov/decompose/ComponentContext;Ljava/lang/String;Lcom/arkivanov/essenty/lifecycle/Lifecycle;ILjava/lang/Object;)Lcom/arkivanov/decompose/ComponentContext;
+	public static final fun childContext (Lcom/arkivanov/decompose/GenericComponentContext;Ljava/lang/String;Lcom/arkivanov/essenty/lifecycle/Lifecycle;)Lcom/arkivanov/decompose/GenericComponentContext;
+	public static synthetic fun childContext$default (Lcom/arkivanov/decompose/GenericComponentContext;Ljava/lang/String;Lcom/arkivanov/essenty/lifecycle/Lifecycle;ILjava/lang/Object;)Lcom/arkivanov/decompose/GenericComponentContext;
+}
+
+public abstract interface class com/arkivanov/decompose/ComponentContextFactory {
+	public abstract fun invoke (Lcom/arkivanov/essenty/lifecycle/Lifecycle;Lcom/arkivanov/essenty/statekeeper/StateKeeper;Lcom/arkivanov/essenty/instancekeeper/InstanceKeeper;Lcom/arkivanov/essenty/backhandler/BackHandler;)Ljava/lang/Object;
+}
+
+public abstract interface class com/arkivanov/decompose/ComponentContextFactoryOwner {
+	public abstract fun getComponentContextFactory ()Lcom/arkivanov/decompose/ComponentContextFactory;
 }
 
 public final class com/arkivanov/decompose/DefaultComponentContext : com/arkivanov/decompose/ComponentContext {
@@ -46,6 +54,7 @@ public final class com/arkivanov/decompose/DefaultComponentContext : com/arkivan
 	public fun <init> (Lcom/arkivanov/essenty/lifecycle/Lifecycle;Lcom/arkivanov/essenty/statekeeper/StateKeeper;Lcom/arkivanov/essenty/instancekeeper/InstanceKeeper;Lcom/arkivanov/essenty/backhandler/BackHandler;)V
 	public synthetic fun <init> (Lcom/arkivanov/essenty/lifecycle/Lifecycle;Lcom/arkivanov/essenty/statekeeper/StateKeeper;Lcom/arkivanov/essenty/instancekeeper/InstanceKeeper;Lcom/arkivanov/essenty/backhandler/BackHandler;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
 	public fun getBackHandler ()Lcom/arkivanov/essenty/backhandler/BackHandler;
+	public fun getComponentContextFactory ()Lcom/arkivanov/decompose/ComponentContextFactory;
 	public fun getInstanceKeeper ()Lcom/arkivanov/essenty/instancekeeper/InstanceKeeper;
 	public fun getLifecycle ()Lcom/arkivanov/essenty/lifecycle/Lifecycle;
 	public fun getStateKeeper ()Lcom/arkivanov/essenty/statekeeper/StateKeeper;
@@ -66,6 +75,9 @@ public abstract interface annotation class com/arkivanov/decompose/ExperimentalD
 public abstract interface annotation class com/arkivanov/decompose/FaultyDecomposeApi : java/lang/annotation/Annotation {
 }
 
+public abstract interface class com/arkivanov/decompose/GenericComponentContext : com/arkivanov/decompose/ComponentContextFactoryOwner, com/arkivanov/essenty/backhandler/BackHandlerOwner, com/arkivanov/essenty/instancekeeper/InstanceKeeperOwner, com/arkivanov/essenty/lifecycle/LifecycleOwner, com/arkivanov/essenty/statekeeper/StateKeeperOwner {
+}
+
 public abstract interface annotation class com/arkivanov/decompose/InternalDecomposeApi : java/lang/annotation/Annotation {
 }
 
@@ -100,10 +112,10 @@ public final class com/arkivanov/decompose/router/children/ChildNavState$Status
 }
 
 public final class com/arkivanov/decompose/router/children/ChildrenFactoryKt {
-	public static final fun children (Lcom/arkivanov/decompose/ComponentContext;Lcom/arkivanov/decompose/router/children/NavigationSource;Ljava/lang/String;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;)Lcom/arkivanov/decompose/value/Value;
-	public static final fun children (Lcom/arkivanov/decompose/ComponentContext;Lcom/arkivanov/decompose/router/children/NavigationSource;Lkotlinx/serialization/KSerializer;Lkotlin/jvm/functions/Function0;Ljava/lang/String;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;)Lcom/arkivanov/decompose/value/Value;
-	public static synthetic fun children$default (Lcom/arkivanov/decompose/ComponentContext;Lcom/arkivanov/decompose/router/children/NavigationSource;Ljava/lang/String;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lcom/arkivanov/decompose/value/Value;
-	public static synthetic fun children$default (Lcom/arkivanov/decompose/ComponentContext;Lcom/arkivanov/decompose/router/children/NavigationSource;Lkotlinx/serialization/KSerializer;Lkotlin/jvm/functions/Function0;Ljava/lang/String;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lcom/arkivanov/decompose/value/Value;
+	public static final fun children (Lcom/arkivanov/decompose/GenericComponentContext;Lcom/arkivanov/decompose/router/children/NavigationSource;Ljava/lang/String;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;)Lcom/arkivanov/decompose/value/Value;
+	public static final fun children (Lcom/arkivanov/decompose/GenericComponentContext;Lcom/arkivanov/decompose/router/children/NavigationSource;Lkotlinx/serialization/KSerializer;Lkotlin/jvm/functions/Function0;Ljava/lang/String;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;)Lcom/arkivanov/decompose/value/Value;
+	public static synthetic fun children$default (Lcom/arkivanov/decompose/GenericComponentContext;Lcom/arkivanov/decompose/router/children/NavigationSource;Ljava/lang/String;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lcom/arkivanov/decompose/value/Value;
+	public static synthetic fun children$default (Lcom/arkivanov/decompose/GenericComponentContext;Lcom/arkivanov/decompose/router/children/NavigationSource;Lkotlinx/serialization/KSerializer;Lkotlin/jvm/functions/Function0;Ljava/lang/String;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lcom/arkivanov/decompose/value/Value;
 }
 
 public abstract interface class com/arkivanov/decompose/router/children/NavState {
@@ -148,10 +160,10 @@ public final class com/arkivanov/decompose/router/pages/ChildPages {
 }
 
 public final class com/arkivanov/decompose/router/pages/ChildPagesFactoryKt {
-	public static final fun childPages (Lcom/arkivanov/decompose/ComponentContext;Lcom/arkivanov/decompose/router/children/NavigationSource;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Ljava/lang/String;Lkotlin/jvm/functions/Function2;ZLkotlin/jvm/functions/Function2;)Lcom/arkivanov/decompose/value/Value;
-	public static final fun childPages (Lcom/arkivanov/decompose/ComponentContext;Lcom/arkivanov/decompose/router/children/NavigationSource;Lkotlinx/serialization/KSerializer;Lkotlin/jvm/functions/Function0;Ljava/lang/String;Lkotlin/jvm/functions/Function2;ZLkotlin/jvm/functions/Function2;)Lcom/arkivanov/decompose/value/Value;
-	public static synthetic fun childPages$default (Lcom/arkivanov/decompose/ComponentContext;Lcom/arkivanov/decompose/router/children/NavigationSource;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Ljava/lang/String;Lkotlin/jvm/functions/Function2;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lcom/arkivanov/decompose/value/Value;
-	public static synthetic fun childPages$default (Lcom/arkivanov/decompose/ComponentContext;Lcom/arkivanov/decompose/router/children/NavigationSource;Lkotlinx/serialization/KSerializer;Lkotlin/jvm/functions/Function0;Ljava/lang/String;Lkotlin/jvm/functions/Function2;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lcom/arkivanov/decompose/value/Value;
+	public static final fun childPages (Lcom/arkivanov/decompose/GenericComponentContext;Lcom/arkivanov/decompose/router/children/NavigationSource;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Ljava/lang/String;Lkotlin/jvm/functions/Function2;ZLkotlin/jvm/functions/Function2;)Lcom/arkivanov/decompose/value/Value;
+	public static final fun childPages (Lcom/arkivanov/decompose/GenericComponentContext;Lcom/arkivanov/decompose/router/children/NavigationSource;Lkotlinx/serialization/KSerializer;Lkotlin/jvm/functions/Function0;Ljava/lang/String;Lkotlin/jvm/functions/Function2;ZLkotlin/jvm/functions/Function2;)Lcom/arkivanov/decompose/value/Value;
+	public static synthetic fun childPages$default (Lcom/arkivanov/decompose/GenericComponentContext;Lcom/arkivanov/decompose/router/children/NavigationSource;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Ljava/lang/String;Lkotlin/jvm/functions/Function2;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lcom/arkivanov/decompose/value/Value;
+	public static synthetic fun childPages$default (Lcom/arkivanov/decompose/GenericComponentContext;Lcom/arkivanov/decompose/router/children/NavigationSource;Lkotlinx/serialization/KSerializer;Lkotlin/jvm/functions/Function0;Ljava/lang/String;Lkotlin/jvm/functions/Function2;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lcom/arkivanov/decompose/value/Value;
 	public static final fun getDefaultPageStatus (ILcom/arkivanov/decompose/router/pages/Pages;)Lcom/arkivanov/decompose/router/children/ChildNavState$Status;
 }
 
@@ -217,10 +229,10 @@ public final class com/arkivanov/decompose/router/slot/ChildSlot {
 }
 
 public final class com/arkivanov/decompose/router/slot/ChildSlotFactoryKt {
-	public static final fun childSlot (Lcom/arkivanov/decompose/ComponentContext;Lcom/arkivanov/decompose/router/children/NavigationSource;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Ljava/lang/String;Lkotlin/jvm/functions/Function0;ZLkotlin/jvm/functions/Function2;)Lcom/arkivanov/decompose/value/Value;
-	public static final fun childSlot (Lcom/arkivanov/decompose/ComponentContext;Lcom/arkivanov/decompose/router/children/NavigationSource;Lkotlinx/serialization/KSerializer;Lkotlin/jvm/functions/Function0;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;)Lcom/arkivanov/decompose/value/Value;
-	public static synthetic fun childSlot$default (Lcom/arkivanov/decompose/ComponentContext;Lcom/arkivanov/decompose/router/children/NavigationSource;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Ljava/lang/String;Lkotlin/jvm/functions/Function0;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lcom/arkivanov/decompose/value/Value;
-	public static synthetic fun childSlot$default (Lcom/arkivanov/decompose/ComponentContext;Lcom/arkivanov/decompose/router/children/NavigationSource;Lkotlinx/serialization/KSerializer;Lkotlin/jvm/functions/Function0;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lcom/arkivanov/decompose/value/Value;
+	public static final fun childSlot (Lcom/arkivanov/decompose/GenericComponentContext;Lcom/arkivanov/decompose/router/children/NavigationSource;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Ljava/lang/String;Lkotlin/jvm/functions/Function0;ZLkotlin/jvm/functions/Function2;)Lcom/arkivanov/decompose/value/Value;
+	public static final fun childSlot (Lcom/arkivanov/decompose/GenericComponentContext;Lcom/arkivanov/decompose/router/children/NavigationSource;Lkotlinx/serialization/KSerializer;Lkotlin/jvm/functions/Function0;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;)Lcom/arkivanov/decompose/value/Value;
+	public static synthetic fun childSlot$default (Lcom/arkivanov/decompose/GenericComponentContext;Lcom/arkivanov/decompose/router/children/NavigationSource;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Ljava/lang/String;Lkotlin/jvm/functions/Function0;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lcom/arkivanov/decompose/value/Value;
+	public static synthetic fun childSlot$default (Lcom/arkivanov/decompose/GenericComponentContext;Lcom/arkivanov/decompose/router/children/NavigationSource;Lkotlinx/serialization/KSerializer;Lkotlin/jvm/functions/Function0;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lcom/arkivanov/decompose/value/Value;
 }
 
 public abstract interface class com/arkivanov/decompose/router/slot/SlotNavigation : com/arkivanov/decompose/router/children/NavigationSource, com/arkivanov/decompose/router/slot/SlotNavigator {
@@ -270,12 +282,12 @@ public final class com/arkivanov/decompose/router/stack/ChildStack {
 }
 
 public final class com/arkivanov/decompose/router/stack/ChildStackFactoryKt {
-	public static final fun childStack (Lcom/arkivanov/decompose/ComponentContext;Lcom/arkivanov/decompose/router/children/NavigationSource;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;)Lcom/arkivanov/decompose/value/Value;
-	public static final fun childStack (Lcom/arkivanov/decompose/ComponentContext;Lcom/arkivanov/decompose/router/children/NavigationSource;Lkotlinx/serialization/KSerializer;Ljava/lang/Object;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;)Lcom/arkivanov/decompose/value/Value;
-	public static final fun childStack (Lcom/arkivanov/decompose/ComponentContext;Lcom/arkivanov/decompose/router/children/NavigationSource;Lkotlinx/serialization/KSerializer;Lkotlin/jvm/functions/Function0;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;)Lcom/arkivanov/decompose/value/Value;
-	public static synthetic fun childStack$default (Lcom/arkivanov/decompose/ComponentContext;Lcom/arkivanov/decompose/router/children/NavigationSource;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lcom/arkivanov/decompose/value/Value;
-	public static synthetic fun childStack$default (Lcom/arkivanov/decompose/ComponentContext;Lcom/arkivanov/decompose/router/children/NavigationSource;Lkotlinx/serialization/KSerializer;Ljava/lang/Object;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lcom/arkivanov/decompose/value/Value;
-	public static synthetic fun childStack$default (Lcom/arkivanov/decompose/ComponentContext;Lcom/arkivanov/decompose/router/children/NavigationSource;Lkotlinx/serialization/KSerializer;Lkotlin/jvm/functions/Function0;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lcom/arkivanov/decompose/value/Value;
+	public static final fun childStack (Lcom/arkivanov/decompose/GenericComponentContext;Lcom/arkivanov/decompose/router/children/NavigationSource;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;)Lcom/arkivanov/decompose/value/Value;
+	public static final fun childStack (Lcom/arkivanov/decompose/GenericComponentContext;Lcom/arkivanov/decompose/router/children/NavigationSource;Lkotlinx/serialization/KSerializer;Ljava/lang/Object;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;)Lcom/arkivanov/decompose/value/Value;
+	public static final fun childStack (Lcom/arkivanov/decompose/GenericComponentContext;Lcom/arkivanov/decompose/router/children/NavigationSource;Lkotlinx/serialization/KSerializer;Lkotlin/jvm/functions/Function0;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;)Lcom/arkivanov/decompose/value/Value;
+	public static synthetic fun childStack$default (Lcom/arkivanov/decompose/GenericComponentContext;Lcom/arkivanov/decompose/router/children/NavigationSource;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lcom/arkivanov/decompose/value/Value;
+	public static synthetic fun childStack$default (Lcom/arkivanov/decompose/GenericComponentContext;Lcom/arkivanov/decompose/router/children/NavigationSource;Lkotlinx/serialization/KSerializer;Ljava/lang/Object;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lcom/arkivanov/decompose/value/Value;
+	public static synthetic fun childStack$default (Lcom/arkivanov/decompose/GenericComponentContext;Lcom/arkivanov/decompose/router/children/NavigationSource;Lkotlinx/serialization/KSerializer;Lkotlin/jvm/functions/Function0;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lcom/arkivanov/decompose/value/Value;
 }
 
 public abstract interface class com/arkivanov/decompose/router/stack/StackNavigation : com/arkivanov/decompose/router/children/NavigationSource, com/arkivanov/decompose/router/stack/StackNavigator {
diff --git a/decompose/api/jvm/decompose.api b/decompose/api/jvm/decompose.api
index f7783110..846f385a 100644
--- a/decompose/api/jvm/decompose.api
+++ b/decompose/api/jvm/decompose.api
@@ -33,12 +33,20 @@ public final class com/arkivanov/decompose/Child$Destroyed : com/arkivanov/decom
 	public fun toString ()Ljava/lang/String;
 }
 
-public abstract interface class com/arkivanov/decompose/ComponentContext : com/arkivanov/essenty/backhandler/BackHandlerOwner, com/arkivanov/essenty/instancekeeper/InstanceKeeperOwner, com/arkivanov/essenty/lifecycle/LifecycleOwner, com/arkivanov/essenty/statekeeper/StateKeeperOwner {
+public abstract interface class com/arkivanov/decompose/ComponentContext : com/arkivanov/decompose/GenericComponentContext {
 }
 
 public final class com/arkivanov/decompose/ComponentContextExtKt {
-	public static final fun childContext (Lcom/arkivanov/decompose/ComponentContext;Ljava/lang/String;Lcom/arkivanov/essenty/lifecycle/Lifecycle;)Lcom/arkivanov/decompose/ComponentContext;
-	public static synthetic fun childContext$default (Lcom/arkivanov/decompose/ComponentContext;Ljava/lang/String;Lcom/arkivanov/essenty/lifecycle/Lifecycle;ILjava/lang/Object;)Lcom/arkivanov/decompose/ComponentContext;
+	public static final fun childContext (Lcom/arkivanov/decompose/GenericComponentContext;Ljava/lang/String;Lcom/arkivanov/essenty/lifecycle/Lifecycle;)Lcom/arkivanov/decompose/GenericComponentContext;
+	public static synthetic fun childContext$default (Lcom/arkivanov/decompose/GenericComponentContext;Ljava/lang/String;Lcom/arkivanov/essenty/lifecycle/Lifecycle;ILjava/lang/Object;)Lcom/arkivanov/decompose/GenericComponentContext;
+}
+
+public abstract interface class com/arkivanov/decompose/ComponentContextFactory {
+	public abstract fun invoke (Lcom/arkivanov/essenty/lifecycle/Lifecycle;Lcom/arkivanov/essenty/statekeeper/StateKeeper;Lcom/arkivanov/essenty/instancekeeper/InstanceKeeper;Lcom/arkivanov/essenty/backhandler/BackHandler;)Ljava/lang/Object;
+}
+
+public abstract interface class com/arkivanov/decompose/ComponentContextFactoryOwner {
+	public abstract fun getComponentContextFactory ()Lcom/arkivanov/decompose/ComponentContextFactory;
 }
 
 public final class com/arkivanov/decompose/DefaultComponentContext : com/arkivanov/decompose/ComponentContext {
@@ -46,6 +54,7 @@ public final class com/arkivanov/decompose/DefaultComponentContext : com/arkivan
 	public fun <init> (Lcom/arkivanov/essenty/lifecycle/Lifecycle;Lcom/arkivanov/essenty/statekeeper/StateKeeper;Lcom/arkivanov/essenty/instancekeeper/InstanceKeeper;Lcom/arkivanov/essenty/backhandler/BackHandler;)V
 	public synthetic fun <init> (Lcom/arkivanov/essenty/lifecycle/Lifecycle;Lcom/arkivanov/essenty/statekeeper/StateKeeper;Lcom/arkivanov/essenty/instancekeeper/InstanceKeeper;Lcom/arkivanov/essenty/backhandler/BackHandler;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
 	public fun getBackHandler ()Lcom/arkivanov/essenty/backhandler/BackHandler;
+	public fun getComponentContextFactory ()Lcom/arkivanov/decompose/ComponentContextFactory;
 	public fun getInstanceKeeper ()Lcom/arkivanov/essenty/instancekeeper/InstanceKeeper;
 	public fun getLifecycle ()Lcom/arkivanov/essenty/lifecycle/Lifecycle;
 	public fun getStateKeeper ()Lcom/arkivanov/essenty/statekeeper/StateKeeper;
@@ -57,6 +66,9 @@ public abstract interface annotation class com/arkivanov/decompose/ExperimentalD
 public abstract interface annotation class com/arkivanov/decompose/FaultyDecomposeApi : java/lang/annotation/Annotation {
 }
 
+public abstract interface class com/arkivanov/decompose/GenericComponentContext : com/arkivanov/decompose/ComponentContextFactoryOwner, com/arkivanov/essenty/backhandler/BackHandlerOwner, com/arkivanov/essenty/instancekeeper/InstanceKeeperOwner, com/arkivanov/essenty/lifecycle/LifecycleOwner, com/arkivanov/essenty/statekeeper/StateKeeperOwner {
+}
+
 public abstract interface annotation class com/arkivanov/decompose/InternalDecomposeApi : java/lang/annotation/Annotation {
 }
 
@@ -84,10 +96,10 @@ public final class com/arkivanov/decompose/router/children/ChildNavState$Status
 }
 
 public final class com/arkivanov/decompose/router/children/ChildrenFactoryKt {
-	public static final fun children (Lcom/arkivanov/decompose/ComponentContext;Lcom/arkivanov/decompose/router/children/NavigationSource;Ljava/lang/String;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;)Lcom/arkivanov/decompose/value/Value;
-	public static final fun children (Lcom/arkivanov/decompose/ComponentContext;Lcom/arkivanov/decompose/router/children/NavigationSource;Lkotlinx/serialization/KSerializer;Lkotlin/jvm/functions/Function0;Ljava/lang/String;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;)Lcom/arkivanov/decompose/value/Value;
-	public static synthetic fun children$default (Lcom/arkivanov/decompose/ComponentContext;Lcom/arkivanov/decompose/router/children/NavigationSource;Ljava/lang/String;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lcom/arkivanov/decompose/value/Value;
-	public static synthetic fun children$default (Lcom/arkivanov/decompose/ComponentContext;Lcom/arkivanov/decompose/router/children/NavigationSource;Lkotlinx/serialization/KSerializer;Lkotlin/jvm/functions/Function0;Ljava/lang/String;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lcom/arkivanov/decompose/value/Value;
+	public static final fun children (Lcom/arkivanov/decompose/GenericComponentContext;Lcom/arkivanov/decompose/router/children/NavigationSource;Ljava/lang/String;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;)Lcom/arkivanov/decompose/value/Value;
+	public static final fun children (Lcom/arkivanov/decompose/GenericComponentContext;Lcom/arkivanov/decompose/router/children/NavigationSource;Lkotlinx/serialization/KSerializer;Lkotlin/jvm/functions/Function0;Ljava/lang/String;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;)Lcom/arkivanov/decompose/value/Value;
+	public static synthetic fun children$default (Lcom/arkivanov/decompose/GenericComponentContext;Lcom/arkivanov/decompose/router/children/NavigationSource;Ljava/lang/String;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lcom/arkivanov/decompose/value/Value;
+	public static synthetic fun children$default (Lcom/arkivanov/decompose/GenericComponentContext;Lcom/arkivanov/decompose/router/children/NavigationSource;Lkotlinx/serialization/KSerializer;Lkotlin/jvm/functions/Function0;Ljava/lang/String;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function2;Lkotlin/jvm/functions/Function3;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lcom/arkivanov/decompose/value/Value;
 }
 
 public abstract interface class com/arkivanov/decompose/router/children/NavState {
@@ -132,10 +144,10 @@ public final class com/arkivanov/decompose/router/pages/ChildPages {
 }
 
 public final class com/arkivanov/decompose/router/pages/ChildPagesFactoryKt {
-	public static final fun childPages (Lcom/arkivanov/decompose/ComponentContext;Lcom/arkivanov/decompose/router/children/NavigationSource;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Ljava/lang/String;Lkotlin/jvm/functions/Function2;ZLkotlin/jvm/functions/Function2;)Lcom/arkivanov/decompose/value/Value;
-	public static final fun childPages (Lcom/arkivanov/decompose/ComponentContext;Lcom/arkivanov/decompose/router/children/NavigationSource;Lkotlinx/serialization/KSerializer;Lkotlin/jvm/functions/Function0;Ljava/lang/String;Lkotlin/jvm/functions/Function2;ZLkotlin/jvm/functions/Function2;)Lcom/arkivanov/decompose/value/Value;
-	public static synthetic fun childPages$default (Lcom/arkivanov/decompose/ComponentContext;Lcom/arkivanov/decompose/router/children/NavigationSource;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Ljava/lang/String;Lkotlin/jvm/functions/Function2;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lcom/arkivanov/decompose/value/Value;
-	public static synthetic fun childPages$default (Lcom/arkivanov/decompose/ComponentContext;Lcom/arkivanov/decompose/router/children/NavigationSource;Lkotlinx/serialization/KSerializer;Lkotlin/jvm/functions/Function0;Ljava/lang/String;Lkotlin/jvm/functions/Function2;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lcom/arkivanov/decompose/value/Value;
+	public static final fun childPages (Lcom/arkivanov/decompose/GenericComponentContext;Lcom/arkivanov/decompose/router/children/NavigationSource;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Ljava/lang/String;Lkotlin/jvm/functions/Function2;ZLkotlin/jvm/functions/Function2;)Lcom/arkivanov/decompose/value/Value;
+	public static final fun childPages (Lcom/arkivanov/decompose/GenericComponentContext;Lcom/arkivanov/decompose/router/children/NavigationSource;Lkotlinx/serialization/KSerializer;Lkotlin/jvm/functions/Function0;Ljava/lang/String;Lkotlin/jvm/functions/Function2;ZLkotlin/jvm/functions/Function2;)Lcom/arkivanov/decompose/value/Value;
+	public static synthetic fun childPages$default (Lcom/arkivanov/decompose/GenericComponentContext;Lcom/arkivanov/decompose/router/children/NavigationSource;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Ljava/lang/String;Lkotlin/jvm/functions/Function2;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lcom/arkivanov/decompose/value/Value;
+	public static synthetic fun childPages$default (Lcom/arkivanov/decompose/GenericComponentContext;Lcom/arkivanov/decompose/router/children/NavigationSource;Lkotlinx/serialization/KSerializer;Lkotlin/jvm/functions/Function0;Ljava/lang/String;Lkotlin/jvm/functions/Function2;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lcom/arkivanov/decompose/value/Value;
 	public static final fun getDefaultPageStatus (ILcom/arkivanov/decompose/router/pages/Pages;)Lcom/arkivanov/decompose/router/children/ChildNavState$Status;
 }
 
@@ -201,10 +213,10 @@ public final class com/arkivanov/decompose/router/slot/ChildSlot {
 }
 
 public final class com/arkivanov/decompose/router/slot/ChildSlotFactoryKt {
-	public static final fun childSlot (Lcom/arkivanov/decompose/ComponentContext;Lcom/arkivanov/decompose/router/children/NavigationSource;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Ljava/lang/String;Lkotlin/jvm/functions/Function0;ZLkotlin/jvm/functions/Function2;)Lcom/arkivanov/decompose/value/Value;
-	public static final fun childSlot (Lcom/arkivanov/decompose/ComponentContext;Lcom/arkivanov/decompose/router/children/NavigationSource;Lkotlinx/serialization/KSerializer;Lkotlin/jvm/functions/Function0;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;)Lcom/arkivanov/decompose/value/Value;
-	public static synthetic fun childSlot$default (Lcom/arkivanov/decompose/ComponentContext;Lcom/arkivanov/decompose/router/children/NavigationSource;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Ljava/lang/String;Lkotlin/jvm/functions/Function0;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lcom/arkivanov/decompose/value/Value;
-	public static synthetic fun childSlot$default (Lcom/arkivanov/decompose/ComponentContext;Lcom/arkivanov/decompose/router/children/NavigationSource;Lkotlinx/serialization/KSerializer;Lkotlin/jvm/functions/Function0;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lcom/arkivanov/decompose/value/Value;
+	public static final fun childSlot (Lcom/arkivanov/decompose/GenericComponentContext;Lcom/arkivanov/decompose/router/children/NavigationSource;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Ljava/lang/String;Lkotlin/jvm/functions/Function0;ZLkotlin/jvm/functions/Function2;)Lcom/arkivanov/decompose/value/Value;
+	public static final fun childSlot (Lcom/arkivanov/decompose/GenericComponentContext;Lcom/arkivanov/decompose/router/children/NavigationSource;Lkotlinx/serialization/KSerializer;Lkotlin/jvm/functions/Function0;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;)Lcom/arkivanov/decompose/value/Value;
+	public static synthetic fun childSlot$default (Lcom/arkivanov/decompose/GenericComponentContext;Lcom/arkivanov/decompose/router/children/NavigationSource;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Ljava/lang/String;Lkotlin/jvm/functions/Function0;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lcom/arkivanov/decompose/value/Value;
+	public static synthetic fun childSlot$default (Lcom/arkivanov/decompose/GenericComponentContext;Lcom/arkivanov/decompose/router/children/NavigationSource;Lkotlinx/serialization/KSerializer;Lkotlin/jvm/functions/Function0;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lcom/arkivanov/decompose/value/Value;
 }
 
 public abstract interface class com/arkivanov/decompose/router/slot/SlotNavigation : com/arkivanov/decompose/router/children/NavigationSource, com/arkivanov/decompose/router/slot/SlotNavigator {
@@ -254,12 +266,12 @@ public final class com/arkivanov/decompose/router/stack/ChildStack {
 }
 
 public final class com/arkivanov/decompose/router/stack/ChildStackFactoryKt {
-	public static final fun childStack (Lcom/arkivanov/decompose/ComponentContext;Lcom/arkivanov/decompose/router/children/NavigationSource;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;)Lcom/arkivanov/decompose/value/Value;
-	public static final fun childStack (Lcom/arkivanov/decompose/ComponentContext;Lcom/arkivanov/decompose/router/children/NavigationSource;Lkotlinx/serialization/KSerializer;Ljava/lang/Object;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;)Lcom/arkivanov/decompose/value/Value;
-	public static final fun childStack (Lcom/arkivanov/decompose/ComponentContext;Lcom/arkivanov/decompose/router/children/NavigationSource;Lkotlinx/serialization/KSerializer;Lkotlin/jvm/functions/Function0;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;)Lcom/arkivanov/decompose/value/Value;
-	public static synthetic fun childStack$default (Lcom/arkivanov/decompose/ComponentContext;Lcom/arkivanov/decompose/router/children/NavigationSource;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lcom/arkivanov/decompose/value/Value;
-	public static synthetic fun childStack$default (Lcom/arkivanov/decompose/ComponentContext;Lcom/arkivanov/decompose/router/children/NavigationSource;Lkotlinx/serialization/KSerializer;Ljava/lang/Object;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lcom/arkivanov/decompose/value/Value;
-	public static synthetic fun childStack$default (Lcom/arkivanov/decompose/ComponentContext;Lcom/arkivanov/decompose/router/children/NavigationSource;Lkotlinx/serialization/KSerializer;Lkotlin/jvm/functions/Function0;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lcom/arkivanov/decompose/value/Value;
+	public static final fun childStack (Lcom/arkivanov/decompose/GenericComponentContext;Lcom/arkivanov/decompose/router/children/NavigationSource;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;)Lcom/arkivanov/decompose/value/Value;
+	public static final fun childStack (Lcom/arkivanov/decompose/GenericComponentContext;Lcom/arkivanov/decompose/router/children/NavigationSource;Lkotlinx/serialization/KSerializer;Ljava/lang/Object;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;)Lcom/arkivanov/decompose/value/Value;
+	public static final fun childStack (Lcom/arkivanov/decompose/GenericComponentContext;Lcom/arkivanov/decompose/router/children/NavigationSource;Lkotlinx/serialization/KSerializer;Lkotlin/jvm/functions/Function0;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;)Lcom/arkivanov/decompose/value/Value;
+	public static synthetic fun childStack$default (Lcom/arkivanov/decompose/GenericComponentContext;Lcom/arkivanov/decompose/router/children/NavigationSource;Lkotlin/jvm/functions/Function0;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lcom/arkivanov/decompose/value/Value;
+	public static synthetic fun childStack$default (Lcom/arkivanov/decompose/GenericComponentContext;Lcom/arkivanov/decompose/router/children/NavigationSource;Lkotlinx/serialization/KSerializer;Ljava/lang/Object;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lcom/arkivanov/decompose/value/Value;
+	public static synthetic fun childStack$default (Lcom/arkivanov/decompose/GenericComponentContext;Lcom/arkivanov/decompose/router/children/NavigationSource;Lkotlinx/serialization/KSerializer;Lkotlin/jvm/functions/Function0;Ljava/lang/String;ZLkotlin/jvm/functions/Function2;ILjava/lang/Object;)Lcom/arkivanov/decompose/value/Value;
 }
 
 public abstract interface class com/arkivanov/decompose/router/stack/StackNavigation : com/arkivanov/decompose/router/children/NavigationSource, com/arkivanov/decompose/router/stack/StackNavigator {
diff --git a/decompose/src/commonMain/kotlin/com/arkivanov/decompose/ComponentContext.kt b/decompose/src/commonMain/kotlin/com/arkivanov/decompose/ComponentContext.kt
index ff6e31dc..ee6b6c18 100644
--- a/decompose/src/commonMain/kotlin/com/arkivanov/decompose/ComponentContext.kt
+++ b/decompose/src/commonMain/kotlin/com/arkivanov/decompose/ComponentContext.kt
@@ -1,12 +1,12 @@
 package com.arkivanov.decompose
 
-import com.arkivanov.essenty.backhandler.BackHandlerOwner
-import com.arkivanov.essenty.instancekeeper.InstanceKeeperOwner
-import com.arkivanov.essenty.lifecycle.LifecycleOwner
-import com.arkivanov.essenty.statekeeper.StateKeeperOwner
-
-interface ComponentContext :
-    LifecycleOwner,
-    StateKeeperOwner,
-    InstanceKeeperOwner,
-    BackHandlerOwner
+/**
+ * A default component context interface provided by Decompose.
+ * Should be passed to component classes via their constructors to
+ * enable features like lifecycle handling, state preservation, navigation,
+ * etc.
+ *
+ * It is also possible to define your own interface with additional
+ * properties or methods, and use that instead of this one.
+ */
+interface ComponentContext : GenericComponentContext<ComponentContext>
diff --git a/decompose/src/commonMain/kotlin/com/arkivanov/decompose/ComponentContextExt.kt b/decompose/src/commonMain/kotlin/com/arkivanov/decompose/ComponentContextExt.kt
index b5735866..0cd75d8f 100644
--- a/decompose/src/commonMain/kotlin/com/arkivanov/decompose/ComponentContextExt.kt
+++ b/decompose/src/commonMain/kotlin/com/arkivanov/decompose/ComponentContextExt.kt
@@ -8,19 +8,19 @@ import com.arkivanov.essenty.lifecycle.Lifecycle
 import com.arkivanov.essenty.lifecycle.doOnDestroy
 
 /**
- * Creates a new instance of child [ComponentContext] and attaches it to the parent (`this`) [ComponentContext].
+ * Creates a new instance of child component context of type [Ctx] and attaches it to the parent (`this`) component context.
  *
- * @param key A key of the child [ComponentContext], must be unique within the parent [ComponentContext].
- * @param lifecycle An optional [Lifecycle] of the child [ComponentContext] to be merged with the parent [Lifecycle],
+ * @param key A key of the child component context, must be unique within the parent context.
+ * @param lifecycle An optional [Lifecycle] of the child component context to be merged with the parent [Lifecycle],
  * can be used for manual control (see [LifecycleRegistry][com.arkivanov.essenty.lifecycle.LifecycleRegistry]).
  * The following conditions apply:
  * - The resulting [Lifecycle] of the child component will honour both the parent (`this`) [Lifecycle] and the supplied one.
  * - The supplied [Lifecycle] must never be destroyed manually.
  */
-fun ComponentContext.childContext(key: String, lifecycle: Lifecycle? = null): ComponentContext {
+fun <Ctx : GenericComponentContext<Ctx>> Ctx.childContext(key: String, lifecycle: Lifecycle? = null): Ctx {
     lifecycle?.doOnDestroy { error("The lifecycle of a child ComponentContext must never be destroyed manually.") }
 
-    return DefaultComponentContext(
+    return componentContextFactory(
         lifecycle = if (lifecycle == null) this.lifecycle else MergedLifecycle(this.lifecycle, lifecycle),
         stateKeeper = stateKeeper.child(key, lifecycle),
         instanceKeeper = instanceKeeper.child(key, lifecycle),
diff --git a/decompose/src/commonMain/kotlin/com/arkivanov/decompose/ComponentContextFactory.kt b/decompose/src/commonMain/kotlin/com/arkivanov/decompose/ComponentContextFactory.kt
new file mode 100644
index 00000000..0519bdfe
--- /dev/null
+++ b/decompose/src/commonMain/kotlin/com/arkivanov/decompose/ComponentContextFactory.kt
@@ -0,0 +1,24 @@
+package com.arkivanov.decompose
+
+import com.arkivanov.essenty.backhandler.BackHandler
+import com.arkivanov.essenty.instancekeeper.InstanceKeeper
+import com.arkivanov.essenty.lifecycle.Lifecycle
+import com.arkivanov.essenty.statekeeper.StateKeeper
+
+/**
+ * Represents a factory that creates new instances of component contexts of type [T].
+ * Used by various navigation models that require creating child component contexts.
+ */
+fun interface ComponentContextFactory<out T : Any> {
+
+    /**
+     * Creates a new instance of component context of type [T], not attached to any
+     * parent component context.
+     */
+    operator fun invoke(
+        lifecycle: Lifecycle,
+        stateKeeper: StateKeeper,
+        instanceKeeper: InstanceKeeper,
+        backHandler: BackHandler,
+    ): T
+}
diff --git a/decompose/src/commonMain/kotlin/com/arkivanov/decompose/ComponentContextFactoryOwner.kt b/decompose/src/commonMain/kotlin/com/arkivanov/decompose/ComponentContextFactoryOwner.kt
new file mode 100644
index 00000000..ab61b47b
--- /dev/null
+++ b/decompose/src/commonMain/kotlin/com/arkivanov/decompose/ComponentContextFactoryOwner.kt
@@ -0,0 +1,18 @@
+package com.arkivanov.decompose
+
+/**
+ * Represents a holder of [ComponentContextFactory].
+ */
+interface ComponentContextFactoryOwner<out T : Any> {
+
+    /**
+     * Returns a [ComponentContextFactory] that creates new instances of
+     * component context of type [T], not attached to any parent component context.
+     *
+     * This property is usually used by various navigation models (such as
+     * [childStack][com.arkivanov.decompose.router.stack.childStack]) for creating
+     * component contexts for child components. If you need to create a child
+     * component context, see [childContext].
+     */
+    val componentContextFactory: ComponentContextFactory<T>
+}
diff --git a/decompose/src/commonMain/kotlin/com/arkivanov/decompose/DefaultComponentContext.kt b/decompose/src/commonMain/kotlin/com/arkivanov/decompose/DefaultComponentContext.kt
index c8aa6cc1..7a8bbcd4 100644
--- a/decompose/src/commonMain/kotlin/com/arkivanov/decompose/DefaultComponentContext.kt
+++ b/decompose/src/commonMain/kotlin/com/arkivanov/decompose/DefaultComponentContext.kt
@@ -9,6 +9,10 @@ import com.arkivanov.essenty.lifecycle.Lifecycle
 import com.arkivanov.essenty.statekeeper.StateKeeper
 import com.arkivanov.essenty.statekeeper.StateKeeperDispatcher
 
+/**
+ * A default implementation of the [ComponentContext] interface.
+ * Can be also used in tests.
+ */
 class DefaultComponentContext(
     override val lifecycle: Lifecycle,
     stateKeeper: StateKeeper? = null,
@@ -19,6 +23,7 @@ class DefaultComponentContext(
     override val stateKeeper: StateKeeper = stateKeeper ?: StateKeeperDispatcher()
     override val instanceKeeper: InstanceKeeper = instanceKeeper ?: InstanceKeeperDispatcher().attachTo(lifecycle)
     override val backHandler: BackHandler = backHandler ?: BackDispatcher()
+    override val componentContextFactory: ComponentContextFactory<ComponentContext> = ComponentContextFactory(::DefaultComponentContext)
 
     constructor(lifecycle: Lifecycle) : this(
         lifecycle = lifecycle,
diff --git a/decompose/src/commonMain/kotlin/com/arkivanov/decompose/GenericComponentContext.kt b/decompose/src/commonMain/kotlin/com/arkivanov/decompose/GenericComponentContext.kt
new file mode 100644
index 00000000..4d923f74
--- /dev/null
+++ b/decompose/src/commonMain/kotlin/com/arkivanov/decompose/GenericComponentContext.kt
@@ -0,0 +1,18 @@
+package com.arkivanov.decompose
+
+import com.arkivanov.essenty.backhandler.BackHandlerOwner
+import com.arkivanov.essenty.instancekeeper.InstanceKeeperOwner
+import com.arkivanov.essenty.lifecycle.LifecycleOwner
+import com.arkivanov.essenty.statekeeper.StateKeeperOwner
+
+/**
+ * A generic component context that extends [LifecycleOwner], [StateKeeperOwner],
+ * [InstanceKeeperOwner] and [BackHandlerOwner] interfaces, and also able to create
+ * new instances of itself via [ComponentContextFactory].
+ */
+interface GenericComponentContext<out T : Any> :
+    LifecycleOwner,
+    StateKeeperOwner,
+    InstanceKeeperOwner,
+    BackHandlerOwner,
+    ComponentContextFactoryOwner<T>
diff --git a/decompose/src/commonMain/kotlin/com/arkivanov/decompose/router/children/ChildrenFactory.kt b/decompose/src/commonMain/kotlin/com/arkivanov/decompose/router/children/ChildrenFactory.kt
index a6ce01be..f75926ba 100644
--- a/decompose/src/commonMain/kotlin/com/arkivanov/decompose/router/children/ChildrenFactory.kt
+++ b/decompose/src/commonMain/kotlin/com/arkivanov/decompose/router/children/ChildrenFactory.kt
@@ -1,7 +1,7 @@
 package com.arkivanov.decompose.router.children
 
 import com.arkivanov.decompose.Child
-import com.arkivanov.decompose.ComponentContext
+import com.arkivanov.decompose.GenericComponentContext
 import com.arkivanov.decompose.Relay
 import com.arkivanov.decompose.backhandler.child
 import com.arkivanov.decompose.mainthread.checkMainThread
@@ -20,7 +20,7 @@ import kotlinx.serialization.Serializable
  * so it's automatically saved and restored. This method can be used if the custom save/restore logic
  * is not required.
  */
-fun <C : Any, T : Any, E : Any, N : NavState<C>, S : Any> ComponentContext.children(
+fun <Ctx : GenericComponentContext<Ctx>, C : Any, T : Any, E : Any, N : NavState<C>, S : Any> Ctx.children(
     source: NavigationSource<E>,
     stateSerializer: KSerializer<N>?,
     initialState: () -> N,
@@ -30,7 +30,7 @@ fun <C : Any, T : Any, E : Any, N : NavState<C>, S : Any> ComponentContext.child
     onStateChanged: (newState: N, oldState: N?) -> Unit = { _, _ -> },
     onEventComplete: (event: E, newState: N, oldState: N) -> Unit = { _, _, _ -> },
     backTransformer: (state: N) -> (() -> N)? = { null },
-    childFactory: (configuration: C, componentContext: ComponentContext) -> T,
+    childFactory: (configuration: C, componentContext: Ctx) -> T,
 ): Value<S> =
     children(
         source = source,
@@ -102,7 +102,7 @@ fun <C : Any, T : Any, E : Any, N : NavState<C>, S : Any> ComponentContext.child
  * @param childFactory a factory function that creates new child component instances.
  * @return an observable [Value] of the resulting children state.
  */
-fun <C : Any, T : Any, E : Any, N : NavState<C>, S : Any> ComponentContext.children(
+fun <Ctx : GenericComponentContext<Ctx>, C : Any, T : Any, E : Any, N : NavState<C>, S : Any> Ctx.children(
     source: NavigationSource<E>,
     key: String,
     initialState: () -> N,
@@ -113,7 +113,7 @@ fun <C : Any, T : Any, E : Any, N : NavState<C>, S : Any> ComponentContext.child
     onStateChanged: (newState: N, oldState: N?) -> Unit = { _, _ -> },
     onEventComplete: (event: E, newState: N, oldState: N) -> Unit = { _, _, _ -> },
     backTransformer: (state: N) -> (() -> N)? = { null },
-    childFactory: (configuration: C, componentContext: ComponentContext) -> T,
+    childFactory: (configuration: C, componentContext: Ctx) -> T,
 ): Value<S> {
     val mainBackHandler = backHandler.child()
     val relay = Relay<NavEvent<E>>()
@@ -220,12 +220,12 @@ private class Holder<out C : Any, T : Any, in E : Any, N : NavState<C>, S : Any>
     }
 }
 
-private fun <C : Any, T : Any, N : NavState<C>> ComponentContext.childrenNavigator(
+private fun <Ctx : GenericComponentContext<Ctx>, C : Any, T : Any, N : NavState<C>> Ctx.childrenNavigator(
     key: String,
     initialState: () -> N,
     saveState: (state: N) -> SerializableContainer?,
     restoreState: (container: SerializableContainer) -> N?,
-    childFactory: (configuration: C, componentContext: ComponentContext) -> T,
+    childFactory: (configuration: C, componentContext: Ctx) -> T,
 ): ChildrenNavigator<C, T, N> {
     val navigator =
         stateKeeper.consume(key = key, strategy = SavedState.serializer()).let { savedState ->
@@ -235,6 +235,7 @@ private fun <C : Any, T : Any, N : NavState<C>> ComponentContext.childrenNavigat
                 lifecycle = lifecycle,
                 retainedInstanceSupplier = { factory -> instanceKeeper.getOrCreate(key = key, factory = factory) },
                 childItemFactory = DefaultChildItemFactory(
+                    contextFactory = componentContextFactory,
                     lifecycle = lifecycle,
                     backHandler = backHandler.child(priority = BackCallback.PRIORITY_DEFAULT + 1),
                     childFactory = childFactory,
diff --git a/decompose/src/commonMain/kotlin/com/arkivanov/decompose/router/children/DefaultChildItemFactory.kt b/decompose/src/commonMain/kotlin/com/arkivanov/decompose/router/children/DefaultChildItemFactory.kt
index b9b23df3..e9ec01b8 100644
--- a/decompose/src/commonMain/kotlin/com/arkivanov/decompose/router/children/DefaultChildItemFactory.kt
+++ b/decompose/src/commonMain/kotlin/com/arkivanov/decompose/router/children/DefaultChildItemFactory.kt
@@ -1,7 +1,6 @@
 package com.arkivanov.decompose.router.children
 
-import com.arkivanov.decompose.ComponentContext
-import com.arkivanov.decompose.DefaultComponentContext
+import com.arkivanov.decompose.ComponentContextFactory
 import com.arkivanov.decompose.backhandler.childBackHandler
 import com.arkivanov.decompose.lifecycle.MergedLifecycle
 import com.arkivanov.essenty.backhandler.BackHandler
@@ -11,10 +10,11 @@ import com.arkivanov.essenty.lifecycle.LifecycleRegistry
 import com.arkivanov.essenty.statekeeper.SerializableContainer
 import com.arkivanov.essenty.statekeeper.StateKeeperDispatcher
 
-internal class DefaultChildItemFactory<C : Any, out T : Any>(
+internal class DefaultChildItemFactory<out Ctx : Any, C : Any, out T : Any>(
+    private val contextFactory: ComponentContextFactory<Ctx>,
     private val lifecycle: Lifecycle,
     private val backHandler: BackHandler,
-    private val childFactory: (configuration: C, ComponentContext) -> T,
+    private val childFactory: (configuration: C, Ctx) -> T,
 ) : ChildItemFactory<C, T> {
 
     override fun invoke(
@@ -31,7 +31,7 @@ internal class DefaultChildItemFactory<C : Any, out T : Any>(
         val component =
             childFactory(
                 configuration,
-                DefaultComponentContext(
+                contextFactory(
                     lifecycle = mergedLifecycle,
                     stateKeeper = stateKeeperDispatcher,
                     instanceKeeper = instanceKeeperRegistry,
diff --git a/decompose/src/commonMain/kotlin/com/arkivanov/decompose/router/pages/ChildPagesFactory.kt b/decompose/src/commonMain/kotlin/com/arkivanov/decompose/router/pages/ChildPagesFactory.kt
index 0aa9b167..84fee183 100644
--- a/decompose/src/commonMain/kotlin/com/arkivanov/decompose/router/pages/ChildPagesFactory.kt
+++ b/decompose/src/commonMain/kotlin/com/arkivanov/decompose/router/pages/ChildPagesFactory.kt
@@ -2,6 +2,7 @@ package com.arkivanov.decompose.router.pages
 
 import com.arkivanov.decompose.ComponentContext
 import com.arkivanov.decompose.ExperimentalDecomposeApi
+import com.arkivanov.decompose.GenericComponentContext
 import com.arkivanov.decompose.router.children.ChildNavState
 import com.arkivanov.decompose.router.children.ChildNavState.Status
 import com.arkivanov.decompose.router.children.NavState
@@ -35,14 +36,14 @@ import kotlinx.serialization.Serializable
  * @return an observable [Value] of [ChildPages].
  */
 @ExperimentalDecomposeApi
-fun <C : Any, T : Any> ComponentContext.childPages(
+fun <Ctx : GenericComponentContext<Ctx>, C : Any, T : Any> Ctx.childPages(
     source: NavigationSource<PagesNavigation.Event<C>>,
     serializer: KSerializer<C>?,
     initialPages: () -> Pages<C> = { Pages() },
     key: String = "DefaultChildPages",
     pageStatus: (index: Int, Pages<C>) -> Status = ::getDefaultPageStatus,
     handleBackButton: Boolean = false,
-    childFactory: (configuration: C, ComponentContext) -> T,
+    childFactory: (configuration: C, Ctx) -> T,
 ): Value<ChildPages<C, T>> =
     childPages(
         source = source,
@@ -104,7 +105,7 @@ private class SerializablePages<out C : Any>(
  * @return an observable [Value] of [ChildPages].
  */
 @ExperimentalDecomposeApi
-fun <C : Any, T : Any> ComponentContext.childPages(
+fun <Ctx : GenericComponentContext<Ctx>, C : Any, T : Any> Ctx.childPages(
     source: NavigationSource<PagesNavigation.Event<C>>,
     initialPages: () -> Pages<C>,
     savePages: (Pages<C>) -> SerializableContainer?,
@@ -112,7 +113,7 @@ fun <C : Any, T : Any> ComponentContext.childPages(
     key: String = "DefaultChildPages",
     pageStatus: (index: Int, Pages<C>) -> Status = ::getDefaultPageStatus,
     handleBackButton: Boolean = false,
-    childFactory: (configuration: C, ComponentContext) -> T,
+    childFactory: (configuration: C, Ctx) -> T,
 ): Value<ChildPages<C, T>> =
     children(
         source = source,
diff --git a/decompose/src/commonMain/kotlin/com/arkivanov/decompose/router/slot/ChildSlotFactory.kt b/decompose/src/commonMain/kotlin/com/arkivanov/decompose/router/slot/ChildSlotFactory.kt
index 5e856435..102d6331 100644
--- a/decompose/src/commonMain/kotlin/com/arkivanov/decompose/router/slot/ChildSlotFactory.kt
+++ b/decompose/src/commonMain/kotlin/com/arkivanov/decompose/router/slot/ChildSlotFactory.kt
@@ -1,7 +1,7 @@
 package com.arkivanov.decompose.router.slot
 
 import com.arkivanov.decompose.Child
-import com.arkivanov.decompose.ComponentContext
+import com.arkivanov.decompose.GenericComponentContext
 import com.arkivanov.decompose.router.children.ChildNavState.Status
 import com.arkivanov.decompose.router.children.NavState
 import com.arkivanov.decompose.router.children.NavigationSource
@@ -27,13 +27,13 @@ import kotlinx.serialization.KSerializer
  * @param childFactory a factory function that creates new child instances.
  * @return an observable [Value] of [ChildSlot].
  */
-fun <C : Any, T : Any> ComponentContext.childSlot(
+fun <Ctx : GenericComponentContext<Ctx>, C : Any, T : Any> Ctx.childSlot(
     source: NavigationSource<SlotNavigation.Event<C>>,
     serializer: KSerializer<C>?,
     initialConfiguration: () -> C? = { null },
     key: String = "DefaultChildSlot",
     handleBackButton: Boolean = false,
-    childFactory: (configuration: C, ComponentContext) -> T,
+    childFactory: (configuration: C, Ctx) -> T,
 ): Value<ChildSlot<C, T>> =
     childSlot(
         source = source,
@@ -72,14 +72,14 @@ fun <C : Any, T : Any> ComponentContext.childSlot(
  * @param childFactory a factory function that creates new child instances.
  * @return an observable [Value] of [ChildSlot].
  */
-fun <C : Any, T : Any> ComponentContext.childSlot(
+fun <Ctx : GenericComponentContext<Ctx>, C : Any, T : Any> Ctx.childSlot(
     source: NavigationSource<SlotNavigation.Event<C>>,
     saveConfiguration: (C?) -> SerializableContainer?,
     restoreConfiguration: (SerializableContainer) -> C?,
     key: String = "DefaultChildSlot",
     initialConfiguration: () -> C? = { null },
     handleBackButton: Boolean = false,
-    childFactory: (configuration: C, ComponentContext) -> T,
+    childFactory: (configuration: C, Ctx) -> T,
 ): Value<ChildSlot<C, T>> =
     children(
         source = source,
diff --git a/decompose/src/commonMain/kotlin/com/arkivanov/decompose/router/stack/ChildStackFactory.kt b/decompose/src/commonMain/kotlin/com/arkivanov/decompose/router/stack/ChildStackFactory.kt
index a5a5e50c..9aa9ae17 100644
--- a/decompose/src/commonMain/kotlin/com/arkivanov/decompose/router/stack/ChildStackFactory.kt
+++ b/decompose/src/commonMain/kotlin/com/arkivanov/decompose/router/stack/ChildStackFactory.kt
@@ -2,6 +2,7 @@ package com.arkivanov.decompose.router.stack
 
 import com.arkivanov.decompose.Child
 import com.arkivanov.decompose.ComponentContext
+import com.arkivanov.decompose.GenericComponentContext
 import com.arkivanov.decompose.router.children.ChildNavState.Status
 import com.arkivanov.decompose.router.children.NavState
 import com.arkivanov.decompose.router.children.NavigationSource
@@ -27,13 +28,13 @@ import kotlinx.serialization.builtins.ListSerializer
  * @param childFactory a factory function that creates new child instances.
  * @return an observable [Value] of [ChildStack].
  */
-fun <C : Any, T : Any> ComponentContext.childStack(
+fun <Ctx: GenericComponentContext<Ctx>, C : Any, T : Any> Ctx.childStack(
     source: NavigationSource<StackNavigation.Event<C>>,
     serializer: KSerializer<C>?,
     initialStack: () -> List<C>,
     key: String = "DefaultChildStack",
     handleBackButton: Boolean = false,
-    childFactory: (configuration: C, ComponentContext) -> T,
+    childFactory: (configuration: C, Ctx) -> T,
 ): Value<ChildStack<C, T>> =
     childStack(
         source = source,
@@ -60,13 +61,13 @@ fun <C : Any, T : Any> ComponentContext.childStack(
 /**
  * A convenience extension function for [ComponentContext.childStack].
  */
-fun <C : Any, T : Any> ComponentContext.childStack(
+fun <Ctx : GenericComponentContext<Ctx>, C : Any, T : Any> Ctx.childStack(
     source: NavigationSource<StackNavigation.Event<C>>,
     serializer: KSerializer<C>?,
     initialConfiguration: C,
     key: String = "DefaultChildStack",
     handleBackButton: Boolean = false,
-    childFactory: (configuration: C, ComponentContext) -> T
+    childFactory: (configuration: C, Ctx) -> T
 ): Value<ChildStack<C, T>> =
     childStack(
         source = source,
@@ -94,14 +95,14 @@ fun <C : Any, T : Any> ComponentContext.childStack(
  * @param childFactory a factory function that creates new child instances.
  * @return an observable [Value] of [ChildStack].
  */
-fun <C : Any, T : Any> ComponentContext.childStack(
+fun <Ctx : GenericComponentContext<Ctx>, C : Any, T : Any> Ctx.childStack(
     source: NavigationSource<StackNavigation.Event<C>>,
     initialStack: () -> List<C>,
     saveStack: (List<C>) -> SerializableContainer?,
     restoreStack: (SerializableContainer) -> List<C>?,
     key: String = "DefaultChildStack",
     handleBackButton: Boolean = false,
-    childFactory: (configuration: C, ComponentContext) -> T,
+    childFactory: (configuration: C, Ctx) -> T,
 ): Value<ChildStack<C, T>> =
     children(
         source = source,
diff --git a/extensions-compose/api/jvm/extensions-compose.api b/extensions-compose/api/jvm/extensions-compose.api
index 2cb6b70c..001c819b 100644
--- a/extensions-compose/api/jvm/extensions-compose.api
+++ b/extensions-compose/api/jvm/extensions-compose.api
@@ -3,7 +3,7 @@ public final class com/arkivanov/decompose/extensions/compose/SubscribeAsStateKt
 }
 
 public final class com/arkivanov/decompose/extensions/compose/lifecycle/LifecycleControllerKt {
-	public static final fun LifecycleController (Lcom/arkivanov/essenty/lifecycle/LifecycleRegistry;Landroidx/compose/ui/window/WindowState;Landroidx/compose/ui/platform/WindowInfo;Landroidx/compose/runtime/Composer;II)V
+	public static final fun LifecycleController (Lcom/arkivanov/essenty/lifecycle/LifecycleRegistry;Landroidx/compose/ui/window/WindowState;Landroidx/compose/runtime/Composer;I)V
 }
 
 public final class com/arkivanov/decompose/extensions/compose/pages/ComposableSingletons$PagesKt {
diff --git a/extensions-compose/src/jvmMain/kotlin/com/arkivanov/decompose/extensions/compose/lifecycle/LifecycleController.kt b/extensions-compose/src/jvmMain/kotlin/com/arkivanov/decompose/extensions/compose/lifecycle/LifecycleController.kt
index 0c0da480..35f56f8e 100644
--- a/extensions-compose/src/jvmMain/kotlin/com/arkivanov/decompose/extensions/compose/lifecycle/LifecycleController.kt
+++ b/extensions-compose/src/jvmMain/kotlin/com/arkivanov/decompose/extensions/compose/lifecycle/LifecycleController.kt
@@ -4,50 +4,24 @@ import androidx.compose.runtime.Composable
 import androidx.compose.runtime.DisposableEffect
 import androidx.compose.runtime.LaunchedEffect
 import androidx.compose.runtime.snapshotFlow
-import androidx.compose.ui.platform.WindowInfo
 import androidx.compose.ui.window.WindowState
 import com.arkivanov.decompose.ExperimentalDecomposeApi
-import com.arkivanov.essenty.lifecycle.Lifecycle
 import com.arkivanov.essenty.lifecycle.LifecycleRegistry
 import com.arkivanov.essenty.lifecycle.create
 import com.arkivanov.essenty.lifecycle.destroy
-import com.arkivanov.essenty.lifecycle.pause
 import com.arkivanov.essenty.lifecycle.resume
-import com.arkivanov.essenty.lifecycle.start
 import com.arkivanov.essenty.lifecycle.stop
-import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.collect
 
-/**
- * Controls (drives) the provided [LifecycleRegistry] according to the window minimized and
- * focused state changes.
- * The lifecycle state is [Lifecycle.State.RESUMED] when the window is focused.
- * The lifecycle state is [Lifecycle.State.CREATED] when the window is minimized.
- * The lifecycle state is [Lifecycle.State.STARTED] otherwise.
- * The [LifecycleRegistry] is destroyed when this function leaves the composition.
- *
- * @param lifecycleRegistry a [LifecycleRegistry] that should be controlled.
- * @param windowState a [WindowState] providing the window minimized state, see [WindowState.isMinimized].
- * @param windowInfo an optional [WindowInfo] providing the window focused state, see [WindowInfo.isWindowFocused].
- * If not provided, the window is always considered focused.
- */
 @ExperimentalDecomposeApi
 @Composable
-fun LifecycleController(
-    lifecycleRegistry: LifecycleRegistry,
-    windowState: WindowState,
-    windowInfo: WindowInfo? = null,
-) {
-    LaunchedEffect(lifecycleRegistry, windowState, windowInfo) {
-        combine(
-            snapshotFlow(windowState::isMinimized),
-            snapshotFlow { windowInfo?.isWindowFocused ?: true },
-            ::Pair,
-        ).collect { (isMinimized, isFocused) ->
-            when {
-                isMinimized -> lifecycleRegistry.stop()
-                isFocused -> lifecycleRegistry.resume()
-                lifecycleRegistry.state == Lifecycle.State.RESUMED -> lifecycleRegistry.pause()
-                else -> lifecycleRegistry.start()
+fun LifecycleController(lifecycleRegistry: LifecycleRegistry, windowState: WindowState) {
+    LaunchedEffect(lifecycleRegistry, windowState) {
+        snapshotFlow(windowState::isMinimized).collect { isMinimized ->
+            if (isMinimized) {
+                lifecycleRegistry.stop()
+            } else {
+                lifecycleRegistry.resume()
             }
         }
     }
diff --git a/sample/app-desktop/src/jvmMain/kotlin/com/arkivanov/sample/app/Main.kt b/sample/app-desktop/src/jvmMain/kotlin/com/arkivanov/sample/app/Main.kt
index 290779f1..48ffaecf 100644
--- a/sample/app-desktop/src/jvmMain/kotlin/com/arkivanov/sample/app/Main.kt
+++ b/sample/app-desktop/src/jvmMain/kotlin/com/arkivanov/sample/app/Main.kt
@@ -15,7 +15,6 @@ import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.remember
 import androidx.compose.runtime.setValue
 import androidx.compose.ui.Modifier
-import androidx.compose.ui.platform.LocalWindowInfo
 import androidx.compose.ui.unit.dp
 import androidx.compose.ui.window.Window
 import androidx.compose.ui.window.application
@@ -58,6 +57,9 @@ fun main() {
 
     application {
         val windowState = rememberWindowState()
+
+        LifecycleController(lifecycle, windowState)
+
         var isCloseRequested by remember { mutableStateOf(false) }
 
         Window(
@@ -65,12 +67,6 @@ fun main() {
             state = windowState,
             title = "Decompose Sample"
         ) {
-            LifecycleController(
-                lifecycleRegistry = lifecycle,
-                windowState = windowState,
-                windowInfo = LocalWindowInfo.current,
-            )
-
             RootContent(root)
 
             if (isCloseRequested) {
diff --git a/sample/shared/shared/src/commonMain/kotlin/com/arkivanov/sample/shared/counters/counter/DefaultCounterComponent.kt b/sample/shared/shared/src/commonMain/kotlin/com/arkivanov/sample/shared/counters/counter/DefaultCounterComponent.kt
index f3ef8ba3..b19067e8 100644
--- a/sample/shared/shared/src/commonMain/kotlin/com/arkivanov/sample/shared/counters/counter/DefaultCounterComponent.kt
+++ b/sample/shared/shared/src/commonMain/kotlin/com/arkivanov/sample/shared/counters/counter/DefaultCounterComponent.kt
@@ -43,7 +43,7 @@ internal class DefaultCounterComponent(
     private val dialogNavigation = SlotNavigation<DialogConfig>()
 
     private val _dialogSlot =
-        childSlot<DialogConfig, DialogComponent>(
+        childSlot(
             source = dialogNavigation,
             serializer = null,
             handleBackButton = true,


Test patch:
diff --git a/decompose/src/commonTest/kotlin/com/arkivanov/decompose/ChildContextWithLifecycleTest.kt b/decompose/src/commonTest/kotlin/com/arkivanov/decompose/ChildContextWithLifecycleTest.kt
index 101ec92d..4655d74d 100644
--- a/decompose/src/commonTest/kotlin/com/arkivanov/decompose/ChildContextWithLifecycleTest.kt
+++ b/decompose/src/commonTest/kotlin/com/arkivanov/decompose/ChildContextWithLifecycleTest.kt
@@ -245,5 +245,6 @@ class ChildContextWithLifecycleTest {
         override val lifecycle: LifecycleRegistry = LifecycleRegistry()
         override val stateKeeper: TestStateKeeperDispatcher = TestStateKeeperDispatcher(savedState)
         override val backHandler: TestBackDispatcher = TestBackDispatcher()
+        override val componentContextFactory: ComponentContextFactory<ComponentContext> = ComponentContextFactory(::DefaultComponentContext)
     }
 }
diff --git a/decompose/src/commonTest/kotlin/com/arkivanov/decompose/ChildContextWithoutLifecycleTest.kt b/decompose/src/commonTest/kotlin/com/arkivanov/decompose/ChildContextWithoutLifecycleTest.kt
index 690089c5..7fc2a70a 100644
--- a/decompose/src/commonTest/kotlin/com/arkivanov/decompose/ChildContextWithoutLifecycleTest.kt
+++ b/decompose/src/commonTest/kotlin/com/arkivanov/decompose/ChildContextWithoutLifecycleTest.kt
@@ -156,5 +156,6 @@ class ChildContextWithoutLifecycleTest {
         override val lifecycle: LifecycleRegistry = LifecycleRegistry()
         override val stateKeeper: TestStateKeeperDispatcher = TestStateKeeperDispatcher(savedState)
         override val backHandler: BackDispatcher = BackDispatcher()
+        override val componentContextFactory: ComponentContextFactory<ComponentContext> = ComponentContextFactory(::DefaultComponentContext)
     }
 }