### Installation Source: https://context7.com/yasan-org/toolkit/llms.txt Instructions for installing different modules of the Yasan Toolkit. ```APIDOC ## Installation ### Core Module ```kotlin implementation("glass.yasan.toolkit:core:") ``` ### Compose Module ```kotlin implementation("glass.yasan.toolkit:compose:") ``` ### About Module ```kotlin implementation("glass.yasan.toolkit:about:") ``` ### Koin Module ```kotlin implementation("glass.yasan.toolkit:koin:") ``` ``` -------------------------------- ### Koin Module for Toolkit Dependencies Source: https://context7.com/yasan-org/toolkit/llms.txt Integrate toolkitModule into your Koin setup to provide essential dependencies like DispatcherProvider, UrlLauncher, and AboutRepository. This module is designed for application-wide use. ```kotlin import glass.yasan.toolkit.koin.toolkitModule import org.koin.core.context.startKoin import org.koin.core.module.dsl.viewModelOf import org.koin.dsl.module // Application module val appModule = module { includes(toolkitModule) // Includes all toolkit dependencies // Your app's dependencies single { ApiServiceImpl(get()) } single { UserRepositoryImpl(get(), get()) } viewModelOf(::MainViewModel) } // Application initialization fun initializeApp() { startKoin { modules(appModule) } } // Usage in ViewModel class MainViewModel( private val dispatcherProvider: DispatcherProvider, private val applicationScope: ApplicationScope, private val urlLauncher: UrlLauncher, private val aboutRepository: AboutRepository ) : ViewModel() { val developer = aboutRepository.developer .stateIn(viewModelScope, SharingStarted.Lazily, Developer()) fun openLink(url: String) { applicationScope.launch { urlLauncher.launch(url) } } } ``` -------------------------------- ### Compose ViewModel Integration with rememberSendViewEvent Source: https://context7.com/yasan-org/toolkit/llms.txt Connects a ToolkitViewModel with Compose UI for lifecycle-aware event sending and action collection. Use `rememberSendViewEvent` to get a function for sending events to the ViewModel and `ViewActionEffect` to observe and react to one-shot actions. ```kotlin import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.runtime.rememberCoroutineScope import glass.yasan.toolkit.compose.viewmodel.ViewActionEffect import glass.yasan.toolkit.compose.viewmodel.rememberSendViewEvent import kotlinx.coroutines.launch import org.koin.compose.viewmodel.koinViewModel @Composable fun CounterScreen() { val viewModel: CounterViewModel = koinViewModel() val viewState by viewModel.viewState.collectAsState() val sendViewEvent = rememberSendViewEvent(viewModel) val scope = rememberCoroutineScope() // Handle one-shot actions from ViewModel ViewActionEffect(viewModel.viewAction) { when (action) { is CounterViewModel.Action.ShowToast -> { showToast(action.message) } is CounterViewModel.Action.Navigate -> { navigateTo(action.route) } } } // UI Column { Text("Count: ${viewState.count}") Button(onClick = { sendViewEvent(CounterViewModel.Event.Increment) }) { Text("Increment") } Button(onClick = { sendViewEvent(CounterViewModel.Event.Decrement) }) { Text("Decrement") } } } ``` -------------------------------- ### Launch URL with UrlLauncher Source: https://context7.com/yasan-org/toolkit/llms.txt Use the UrlLauncher to open URLs in the system browser. Handles different result types for success and various failure scenarios. ```kotlin import glass.yasan.toolkit.core.url.UrlLauncher import glass.yasan.toolkit.core.url.UrlLaunchResult import org.koin.core.component.inject class MyRepository : KoinComponent { private val urlLauncher: UrlLauncher by inject() suspend fun openWebsite() { when (val result = urlLauncher.launch("https://example.com")) { is UrlLaunchResult.Success -> { println("URL opened successfully") } is UrlLaunchResult.Failure.InvalidUrl -> { println("Invalid URL format") } is UrlLaunchResult.Failure.Unsupported -> { println("URL scheme not supported on this platform") } is UrlLaunchResult.Failure.Error -> { println("Error: ${result.exception.message}") } } } // Simplified usage with callback suspend fun openEmail() { urlLauncher.launch("mailto:contact@example.com") { failure -> when (failure) { is UrlLaunchResult.Failure.InvalidUrl -> handleInvalidUrl() is UrlLaunchResult.Failure.Unsupported -> handleUnsupported() is UrlLaunchResult.Failure.Error -> handleError(failure.exception) } } } } ``` -------------------------------- ### Display Developer Information with Links Source: https://context7.com/yasan-org/toolkit/llms.txt Use ToolkitDeveloperContent to display full developer information including clickable social links. Customize analytics tracking for link clicks. ```kotlin import androidx.compose.runtime.Composable import glass.yasan.toolkit.about.presentation.compose.ToolkitDeveloperContent import glass.yasan.toolkit.about.presentation.compose.ToolkitDeveloperBanner @Composable fun AboutScreen() { LazyColumn { item { // Full developer content with all links ToolkitDeveloperContent( onTrackDeveloperLinkClick = { link -> // Track analytics before link is opened analytics.trackEvent("developer_link_click", mapOf( "link_name" to link.name, "link_type" to link.type.name )) } ) } } } @Composable fun AppFooter() { // Compact banner with horizontal logo ToolkitDeveloperBanner() } ``` -------------------------------- ### Compose Preview with BooleanPreviewParameterProvider Source: https://context7.com/yasan-org/toolkit/llms.txt Provides boolean values for Compose previews using BooleanPreviewParameterProvider and NullableBooleanPreviewParameterProvider. Use these to test composables that depend on boolean states. ```kotlin import androidx.compose.runtime.Composable import glass.yasan.toolkit.compose.preview.BooleanPreviewParameterProvider import glass.yasan.toolkit.compose.preview.NullableBooleanPreviewParameterProvider import org.jetbrains.compose.ui.tooling.preview.Preview import org.jetbrains.compose.ui.tooling.preview.PreviewParameter @Preview @Composable fun ToggleButtonPreview( @PreviewParameter(BooleanPreviewParameterProvider::class) isEnabled: Boolean ) { ToggleButton( isEnabled = isEnabled, onClick = {} ) } @Preview @Composable fun CheckboxPreview( @PreviewParameter(NullableBooleanPreviewParameterProvider::class) isChecked: Boolean? ) { TriStateCheckbox( state = when (isChecked) { true -> ToggleableState.On false -> ToggleableState.Off null -> ToggleableState.Indeterminate }, onClick = {} ) } ``` -------------------------------- ### UrlLauncher - Cross-Platform URL Launching Source: https://context7.com/yasan-org/toolkit/llms.txt The UrlLauncher interface provides a platform-agnostic way to open URLs in the system browser or handle mailto links. ```APIDOC ## UrlLauncher - Cross-Platform URL Launching ### Description The `UrlLauncher` interface provides a platform-agnostic way to open URLs in the system browser or handle mailto links. It returns a sealed result type for proper error handling. ### Request Example ```kotlin import glass.yasan.toolkit.core.url.UrlLauncher import glass.yasan.toolkit.core.url.UrlLaunchResult import org.koin.core.component.inject class MyRepository : KoinComponent { private val urlLauncher: UrlLauncher by inject() suspend fun openWebsite() { when (val result = urlLauncher.launch("https://example.com")) { is UrlLaunchResult.Success -> { println("URL opened successfully") } is UrlLaunchResult.Failure.InvalidUrl -> { println("Invalid URL format") } is UrlLaunchResult.Failure.Unsupported -> { println("URL scheme not supported on this platform") } is UrlLaunchResult.Failure.Error -> { println("Error: ${result.exception.message}") } } } // Simplified usage with callback suspend fun openEmail() { urlLauncher.launch("mailto:contact@example.com") { failure -> when (failure) { is UrlLaunchResult.Failure.InvalidUrl -> handleInvalidUrl() is UrlLaunchResult.Failure.Unsupported -> handleUnsupported() is UrlLaunchResult.Failure.Error -> handleError(failure.exception) } } } } ``` ``` -------------------------------- ### Developer Model with Social Links Source: https://context7.com/yasan-org/toolkit/llms.txt Represents developer information including name, biography, and social links. Automatically detects link types and provides appropriate icons. Supports Gravatar for profile pictures. ```kotlin import glass.yasan.toolkit.about.domain.model.Developer import kotlinx.collections.immutable.persistentListOf val developer = Developer( name = "John Doe", biography = "Mobile Developer & Designer", links = persistentListOf( Developer.Link(name = "Website", url = "https://johndoe.dev"), Developer.Link(name = "Email", url = "mailto:john@example.com"), Developer.Link(name = "GitHub", url = "https://github.com/johndoe"), Developer.Link(name = "Mastodon", url = "https://mastodon.social/@johndoe"), Developer.Link(name = "Play Store", url = "https://play.google.com/store/apps/dev?id=123"), ) ) // Link types are automatically detected developer.links.forEach { link -> println("${link.name}: ${link.type}") // Outputs: Website: WEBSITE, Email: EMAIL, etc. // link.icon provides the appropriate DrawableResource } // Gravatar support val picture = Developer.Picture( gravatar = Developer.Picture.Gravatar(id = "md5-hash-of-email") ) val avatarUrl = picture.gravatar.getImageUrl(size = 256) ``` -------------------------------- ### Use DispatcherProvider for Coroutines Source: https://context7.com/yasan-org/toolkit/llms.txt Inject DispatcherProvider to abstract coroutine dispatchers for platform-specific execution and testability. Use withContext to switch dispatchers. ```kotlin import glass.yasan.toolkit.core.coroutines.DispatcherProvider import glass.yasan.toolkit.core.coroutines.createDefaultDispatcherProvider import kotlinx.coroutines.withContext class DataRepository(private val dispatcherProvider: DispatcherProvider) { suspend fun fetchData(): List = withContext(dispatcherProvider.io) { // Perform I/O operations on the IO dispatcher listOf("item1", "item2", "item3") } suspend fun processData(data: List): Result = withContext(dispatcherProvider.default) { // CPU-intensive work on the Default dispatcher Result.success(data.size) } } // Create default dispatcher provider val dispatcherProvider = createDefaultDispatcherProvider() // Provides: main, io, default, unconfined dispatchers ``` -------------------------------- ### Compose Spacer Utilities Source: https://context7.com/yasan-org/toolkit/llms.txt Provides composable functions and lazy list extensions for creating explicit horizontal and vertical spacers. Use `VerticalSpacer` and `HorizontalSpacer` for fixed dimensions, and `verticalSpacerItem` for lazy lists. ```kotlin import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.runtime.Composable import androidx.compose.ui.unit.dp import glass.yasan.toolkit.compose.spacer.HorizontalSpacer import glass.yasan.toolkit.compose.spacer.Spacer import glass.yasan.toolkit.compose.spacer.VerticalSpacer import glass.yasan.toolkit.compose.spacer.horizontalSpacerItem import glass.yasan.toolkit.compose.spacer.verticalSpacerItem @Composable fun ProfileScreen() { Column { Avatar() VerticalSpacer(height = 16.dp) Username() VerticalSpacer(height = 8.dp) Bio() } } ``` ```kotlin import androidx.compose.runtime.Composable import glass.yasan.toolkit.compose.spacer.HorizontalSpacer @Composable fun ButtonRow() { Row { PrimaryButton() HorizontalSpacer(width = 12.dp) SecondaryButton() } } ``` ```kotlin import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.runtime.Composable import androidx.compose.ui.unit.dp import glass.yasan.toolkit.compose.spacer.verticalSpacerItem @Composable fun SettingsList() { LazyColumn { item { Header() } verticalSpacerItem(height = 16.dp) items(settings) { SettingItem(setting) } verticalSpacerItem(height = 32.dp) // Bottom padding } } ``` -------------------------------- ### MVI Architecture Base ViewModel Source: https://context7.com/yasan-org/toolkit/llms.txt Implement the Model-View-Intent (MVI) pattern using this abstract ViewModel. It provides built-in state management and handles ViewState, ViewEvent, and ViewAction types for structured UI logic. ```kotlin import glass.yasan.toolkit.compose.viewmodel.ToolkitViewModel import glass.yasan.toolkit.compose.viewmodel.ViewAction import glass.yasan.toolkit.compose.viewmodel.ViewEvent import glass.yasan.toolkit.compose.viewmodel.ViewState class CounterViewModel : ToolkitViewModel< CounterViewModel.State, CounterViewModel.Event, CounterViewModel.Action >() { data class State( val count: Int = 0, val isLoading: Boolean = false ) : ViewState sealed interface Event : ViewEvent { data object Increment : Event data object Decrement : Event data class SetValue(val value: Int) : Event } sealed interface Action : ViewAction { data class ShowToast(val message: String) : Action data class Navigate(val route: String) : Action } override fun defaultViewState(): State = State() override suspend fun onViewEvent(event: Event) { when (event) { Event.Increment -> { updateViewState { copy(count = count + 1) } if (viewState.value.count == 10) { sendViewAction(Action.ShowToast("You reached 10!")) } } Event.Decrement -> { updateViewState { copy(count = count - 1) } } is Event.SetValue -> { updateViewState { copy(count = event.value) } } } } } ``` -------------------------------- ### ToolkitViewModel - MVI Architecture Base Class Source: https://context7.com/yasan-org/toolkit/llms.txt An abstract ViewModel class that implements the Model-View-Intent (MVI) pattern. It provides built-in state management and event handling using generic ViewState, ViewEvent, and ViewAction types. ```APIDOC ## ToolkitViewModel - MVI Architecture Base Class An abstract ViewModel class implementing the Model-View-Intent (MVI) pattern with ViewState, ViewEvent, and ViewAction types. Provides built-in state management and event handling. ### Overview `ToolkitViewModel` simplifies MVI implementation by providing a structured way to manage UI state, handle user intents, and emit side effects (ViewActions). ### Generic Types - `ViewState`: Represents the state of the UI. - `ViewEvent`: Represents events triggered by the UI that the ViewModel should handle. - `ViewAction`: Represents side effects or actions that the ViewModel wants to communicate back to the UI (e.g., showing a toast, navigation). ### Example Implementation ```kotlin import glass.yasan.toolkit.compose.viewmodel.ToolkitViewModel import glass.yasan.toolkit.compose.viewmodel.ViewAction import glass.yasan.toolkit.compose.viewmodel.ViewEvent import glass.yasan.toolkit.compose.viewmodel.ViewState class CounterViewModel : ToolkitViewModel< CounterViewModel.State, CounterViewModel.Event, CounterViewModel.Action >() { data class State( val count: Int = 0, val isLoading: Boolean = false ) : ViewState sealed interface Event : ViewEvent { data object Increment : Event data object Decrement : Event data class SetValue(val value: Int) : Event } sealed interface Action : ViewAction { data class ShowToast(val message: String) : Action data class Navigate(val route: String) : Action } override fun defaultViewState(): State = State() override suspend fun onViewEvent(event: Event) { when (event) { Event.Increment -> { updateViewState { copy(count = count + 1) } if (viewState.value.count == 10) { sendViewAction(Action.ShowToast("You reached 10!")) } } Event.Decrement -> { updateViewState { copy(count = count - 1) } } is Event.SetValue -> { updateViewState { copy(count = event.value) } } } } } ``` ### Key Methods - `defaultViewState()`: Returns the initial state of the ViewModel. - `onViewEvent(event: ViewEvent)`: Handles incoming ViewEvents. - `updateViewState { ... }`: Updates the current ViewState. - `sendViewAction(action: ViewAction)`: Sends a ViewAction to be handled by the UI. ``` -------------------------------- ### Synchronously Collect First Flow Value Source: https://context7.com/yasan-org/toolkit/llms.txt The `firstBlocking` extension collects the first emitted value from a Flow synchronously. Use this when you need to block the current thread to obtain an initial value, such as during application startup or ViewModel initialization. ```kotlin import glass.yasan.toolkit.core.coroutines.firstBlocking import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.flowOf val configFlow: Flow = flowOf(AppConfig.default()) // Get first value synchronously (blocks current thread) val initialConfig: AppConfig = configFlow.firstBlocking() // Useful for ViewModel initialization class SettingsViewModel(settingsRepository: SettingsRepository) { private val initialSettings = settingsRepository.settings.firstBlocking() } ``` -------------------------------- ### Coroutine Extensions - Cancellation Handling Source: https://context7.com/yasan-org/toolkit/llms.txt Provides extension functions for safely handling CancellationException in coroutines, ensuring proper cancellation propagation and allowing for fallback logic. ```APIDOC ## Coroutine Extensions - Cancellation Handling Utilities Extension functions for safely handling `CancellationException` in coroutines, ensuring proper cancellation propagation. ### safeFetch Safely fetches data from a network source, returning null on error but rethrowing `CancellationException`. ```kotlin import glass.yasan.toolkit.core.coroutines.getOrNullOrRethrowCancellation suspend fun safeFetch(): String? { return runCatching { fetchFromNetwork() }.getOrNullOrRethrowCancellation() } ``` ### fetchWithFallback Fetches data from a network source, providing a fallback value for non-cancellation errors and rethrowing `CancellationException`. ```kotlin import glass.yasan.toolkit.core.coroutines.getOrElseOrRethrowCancellation suspend fun fetchWithFallback(): String { return runCatching { fetchFromNetwork() }.getOrElseOrRethrowCancellation { // Handle non-cancellation errors "fallback value" } } ``` ### manualErrorHandling Demonstrates manual error handling with `rethrowCancellation` to selectively rethrow `CancellationException` while handling other exceptions. ```kotlin import glass.yasan.toolkit.core.coroutines.rethrowCancellation suspend fun manualErrorHandling() { try { riskyOperation() } catch (e: Exception) { e.rethrowCancellation() // Rethrow if it's a cancellation // Handle other exceptions logError(e) } } ``` ``` -------------------------------- ### Add About Module Dependency Source: https://github.com/yasan-org/toolkit/blob/main/README.md Include this dependency to add the 'About' module from the Yasan Toolkit to your Kotlin Multiplatform project. ```kotlin implementation("glass.yasan.toolkit:about:") ``` -------------------------------- ### Compose VerticalAnimatedVisibility for Content Animation Source: https://context7.com/yasan-org/toolkit/llms.txt A convenience composable that simplifies adding fade and vertical expand/shrink animations for showing and hiding content. It requires a `visible` state to control the animation. ```kotlin import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import glass.yasan.toolkit.compose.animation.VerticalAnimatedVisibility @Composable fun ExpandableCard() { var isExpanded by remember { mutableStateOf(false) } Column { Row( modifier = Modifier.clickable { isExpanded = !isExpanded } ) { Text("Click to expand") Icon( imageVector = if (isExpanded) Icons.Default.ExpandLess else Icons.Default.ExpandMore ) } VerticalAnimatedVisibility(visible = isExpanded) { Column { Text("Additional details go here") Text("This content fades in and expands vertically") Button(onClick = { /* action */ }) { Text("Action Button") } } } } } ``` -------------------------------- ### Add Koin Module Dependency Source: https://github.com/yasan-org/toolkit/blob/main/README.md Include this dependency to integrate Koin support from the Yasan Toolkit into your Kotlin Multiplatform project. ```kotlin implementation("glass.yasan.toolkit:koin:") ``` -------------------------------- ### Collect Flow with Lifecycle Blocking Source: https://context7.com/yasan-org/toolkit/llms.txt Collects a Flow with lifecycle awareness and retrieves the initial value synchronously using collectAsStateWithLifecycleBlocking. Useful for ensuring UI has an initial state before lifecycle events occur. ```kotlin import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import glass.yasan.toolkit.compose.coroutines.collectAsStateWithLifecycleBlocking import kotlinx.coroutines.flow.Flow @Composable fun UserProfileScreen(userFlow: Flow) { // Blocks to get initial value, then collects lifecycle-aware val user by userFlow.collectAsStateWithLifecycleBlocking() Column { Text("Name: ${user.name}") Text("Email: ${user.email}") } } ``` -------------------------------- ### Add Compose Module Dependency Source: https://github.com/yasan-org/toolkit/blob/main/README.md Include this dependency to add Compose-related utilities from the Yasan Toolkit to your Kotlin Multiplatform project. ```kotlin implementation("glass.yasan.toolkit:compose:") ``` -------------------------------- ### Define ApplicationScope for Coroutines Source: https://context7.com/yasan-org/toolkit/llms.txt Utilize the ApplicationScope type alias for CoroutineScope to manage application-wide coroutines that should persist. Typically set up with Koin. ```kotlin import glass.yasan.toolkit.core.coroutines.ApplicationScope import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.launch class AppInitializer( private val applicationScope: ApplicationScope, private val dispatcherProvider: DispatcherProvider ) { fun initialize() { applicationScope.launch { // Long-running initialization that survives configuration changes loadConfiguration() initializeAnalytics() warmupCaches() } } } // Typical setup with Koin val applicationScope: ApplicationScope = CoroutineScope( SupervisorJob() + dispatcherProvider.default ) ``` -------------------------------- ### Safely Handle Coroutine Cancellation Exceptions Source: https://context7.com/yasan-org/toolkit/llms.txt Use these extensions to safely handle CancellationException in coroutines. They ensure that cancellation is rethrown when necessary, while allowing other exceptions to be handled or returned as null/default values. ```kotlin import glass.yasan.toolkit.core.coroutines.isCancellationToRethrow import glass.yasan.toolkit.core.coroutines.rethrowCancellation import glass.yasan.toolkit.core.coroutines.getOrNullOrRethrowCancellation import glass.yasan.toolkit.core.coroutines.getOrElseOrRethrowCancellation suspend fun safeFetch(): String? { return runCatching { fetchFromNetwork() }.getOrNullOrRethrowCancellation() // Returns null on error, but rethrows CancellationException } ``` ```kotlin suspend fun fetchWithFallback(): String { return runCatching { fetchFromNetwork() }.getOrElseOrRethrowCancellation { // Handle non-cancellation errors "fallback value" } } ``` ```kotlin suspend fun manualErrorHandling() { try { riskyOperation() } catch (e: Exception) { e.rethrowCancellation() // Rethrow if it's a cancellation // Handle other exceptions logError(e) } } ``` -------------------------------- ### DispatcherProvider - Coroutine Dispatchers Abstraction Source: https://context7.com/yasan-org/toolkit/llms.txt The DispatcherProvider interface provides platform-specific coroutine dispatchers, enabling testable code by allowing dispatcher injection. ```APIDOC ## DispatcherProvider - Coroutine Dispatchers Abstraction ### Description The `DispatcherProvider` interface provides platform-specific coroutine dispatchers, enabling testable code by allowing dispatcher injection. ### Request Example ```kotlin import glass.yasan.toolkit.core.coroutines.DispatcherProvider import glass.yasan.toolkit.core.coroutines.createDefaultDispatcherProvider import kotlinx.coroutines.withContext class DataRepository(private val dispatcherProvider: DispatcherProvider) { suspend fun fetchData(): List = withContext(dispatcherProvider.io) { // Perform I/O operations on the IO dispatcher listOf("item1", "item2", "item3") } suspend fun processData(data: List): Result = withContext(dispatcherProvider.default) { // CPU-intensive work on the Default dispatcher Result.success(data.size) } } // Create default dispatcher provider val dispatcherProvider = createDefaultDispatcherProvider() // Provides: main, io, default, unconfined dispatchers ``` ``` -------------------------------- ### firstBlocking - Blocking Flow Collection Source: https://context7.com/yasan-org/toolkit/llms.txt A utility function to synchronously retrieve the first value emitted by a Kotlin Flow. This is useful for initialization scenarios where blocking the current thread is acceptable. ```APIDOC ## firstBlocking - Blocking Flow Collection A utility function to synchronously get the first value from a Flow, useful for initialization scenarios on non-web platforms. ### Usage Collect the first value from a Flow, blocking the current thread until a value is emitted. ```kotlin import glass.yasan.toolkit.core.coroutines.firstBlocking import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.flowOf val configFlow: Flow = flowOf(AppConfig.default()) // Get first value synchronously (blocks current thread) val initialConfig: AppConfig = configFlow.firstBlocking() // Useful for ViewModel initialization class SettingsViewModel(settingsRepository: SettingsRepository) { private val initialSettings = settingsRepository.settings.firstBlocking() } ``` ``` -------------------------------- ### Add Core Module Dependency Source: https://github.com/yasan-org/toolkit/blob/main/README.md Include this dependency to add the core functionality of the Yasan Toolkit to your Kotlin Multiplatform project. ```kotlin implementation("glass.yasan.toolkit:core:") ``` -------------------------------- ### Define FormError with ResolvableString Source: https://context7.com/yasan-org/toolkit/llms.txt Defines a sealed interface for form errors, supporting string resources, formatted resources, and literal strings for error messages. Use this to create flexible and localized form validation feedback. ```kotlin import androidx.compose.runtime.Composable import glass.yasan.toolkit.compose.string.ResolvableString import glass.yasan.toolkit.core.annotation.ExperimentalToolkitApi import org.jetbrains.compose.resources.StringResource @OptIn(ExperimentalToolkitApi::class) sealed interface FormError { val message: ResolvableString data object EmptyField : FormError { override val message = ResolvableString.Resource(Res.string.error_empty_field) } data class TooShort(val minLength: Int) : FormError { override val message = ResolvableString.ResourceWithArgs( resource = Res.string.error_too_short, formatArgs = listOf(minLength) ) } data class Custom(val text: String) : FormError { override val message = ResolvableString.Literal(text) } } @OptIn(ExperimentalToolkitApi::class) @Composable fun ErrorMessage(error: FormError) { Text( text = error.message.resolve(), color = MaterialTheme.colorScheme.error ) } ``` -------------------------------- ### ApplicationScope - Application-Scoped CoroutineScope Source: https://context7.com/yasan-org/toolkit/llms.txt A type alias for CoroutineScope intended for application-wide coroutine operations that should outlive individual components. ```APIDOC ## ApplicationScope - Application-Scoped CoroutineScope ### Description A type alias for `CoroutineScope` intended for application-wide coroutine operations that should outlive individual components. ### Request Example ```kotlin import glass.yasan.toolkit.core.coroutines.ApplicationScope import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.launch class AppInitializer( private val applicationScope: ApplicationScope, private val dispatcherProvider: DispatcherProvider ) { fun initialize() { applicationScope.launch { // Long-running initialization that survives configuration changes loadConfiguration() initializeAnalytics() warmupCaches() } } } // Typical setup with Koin val applicationScope: ApplicationScope = CoroutineScope( SupervisorJob() + dispatcherProvider.default ) ``` ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.