package dev.inmo.jsuikit.elements import androidx.compose.runtime.Composable import androidx.compose.runtime.DisposableEffectResult import dev.inmo.jsuikit.modifiers.* import org.jetbrains.compose.web.dom.* import org.w3c.dom.HTMLDivElement import org.w3c.dom.HTMLElement import org.w3c.dom.events.Event import kotlin.random.Random import kotlin.random.nextUInt private class DialogDisposableEffectResult( private val element: HTMLElement, private val onDispose: (() -> Unit)?, private val onDisposed: (() -> Unit)? ) : DisposableEffectResult { override fun dispose() { onDispose?.invoke() UIKit.modal("#${element.id}") ?.hide() onDisposed?.invoke() } } @Composable fun Dialog( vararg modifiers: UIKitModifier, attributesCustomizer: AttrBuilderContext = {}, onHide: (() -> Unit)? = null, onHidden: (() -> Unit)? = null, dialogAttrsBuilder: AttrBuilderContext? = null, headerAttrsBuilder: AttrBuilderContext? = null, headerBuilder: ContentBuilder? = null, afterHeaderBuilder: ContentBuilder? = null, beforeFooterBuilder: ContentBuilder? = null, footerAttrsBuilder: AttrBuilderContext? = null, footerBuilder: ContentBuilder? = null, bodyAttrsBuilder: AttrBuilderContext? = null, autoShow: Boolean = true, bodyBuilder: ContentBuilder ) { Div( { if (modifiers.none { it is UIKitModal.WithCustomAttributes }) { include(UIKitModal) } id("dialog${Random.nextUInt()}") include(*modifiers) attributesCustomizer() } ) { Div( { include(UIKitModal.Dialog) dialogAttrsBuilder ?.let { it() } ?: include(UIKitMargin.Auto.Vertical) } ) { headerBuilder ?.let { Div( { include(UIKitModal.Header) headerAttrsBuilder ?.let { it() } } ) { it() } } afterHeaderBuilder ?.let { it() } Div( { include(UIKitModal.Body) bodyAttrsBuilder ?.let { it() } } ) { bodyBuilder() } beforeFooterBuilder ?.let { it() } footerBuilder ?.let { Div( { include(UIKitModal.Footer) footerAttrsBuilder ?.let { it() } ?: include(UIKitText.Alignment.Horizontal.Right) } ) { it() } } } DisposableRefEffect { DialogDisposableEffectResult(it, onHide, onHidden) } DomSideEffect { htmlElement -> var wrapper: (Event) -> Unit = {} wrapper = { it: Event -> htmlElement.removeEventListener("hidden", wrapper) htmlElement.remove() onHidden ?.invoke() } htmlElement.addEventListener("hidden", wrapper) if (autoShow) { UIKit.modal("#${htmlElement.id}") ?.show() } } } } @Composable fun Dialog( title: String, vararg modifiers: UIKitModifier, hide: (() -> Unit)? = null, hidden: (() -> Unit)? = null, footerBuilder: (@Composable () -> Unit)? = null, attributesCustomizer: AttrBuilderContext = {}, autoShow: Boolean = true, bodyBuilder: @Composable () -> Unit ) = Dialog( modifiers = modifiers, headerBuilder = { H2({ include(UIKitModal.Title) }) { Text(title) } }, onHide = hide, onHidden = hidden, footerBuilder = footerBuilder ?.let { _ -> { footerBuilder() } }, attributesCustomizer = { attributesCustomizer() }, autoShow = autoShow, bodyBuilder = { bodyBuilder() } )