Skip to content

Commit

Permalink
support punching a hole in Compose UI to blend with HTMLElement (#215)
Browse files Browse the repository at this point in the history
  • Loading branch information
sargunv authored Dec 31, 2024
1 parent e5f281d commit 18ce6fe
Show file tree
Hide file tree
Showing 5 changed files with 20 additions and 7 deletions.
Original file line number Diff line number Diff line change
@@ -1,21 +1,31 @@
package dev.sargunv.composehtmlinterop

import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.drawBehind
import androidx.compose.ui.graphics.BlendMode
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.onGloballyPositioned
import androidx.compose.ui.platform.LocalDensity

@Composable
public fun <T : HTMLElement> HtmlElement(
factory: () -> T,
update: (T) -> Unit = {},
zIndex: String = "auto",
modifier: Modifier = Modifier,
) {
val density = LocalDensity.current
val container = rememberContainerNode()
val container = rememberContainerNode(zIndex)
val child = rememberDomNode(parent = container, factory = factory)
SnapshotEffect(child) { update(it) }
Box(modifier.onGloballyPositioned { container.matchLayout(it, density) })
Box(
modifier
.fillMaxSize()
.onGloballyPositioned { container.matchLayout(it, density) }
.drawBehind { drawRect(color = Color.Transparent, size = size, blendMode = BlendMode.Clear) }
)
HtmlFocusAdapter(container)
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ public expect abstract class HTMLElement {

internal fun Dp.toCssValue(): String = "${value}px"

@Composable internal expect fun rememberContainerNode(): HTMLElement
@Composable internal expect fun rememberContainerNode(zIndex: String): HTMLElement

internal expect fun HTMLElement.matchLayout(layoutCoordinates: LayoutCoordinates, density: Density)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,12 @@ import kotlinx.browser.document
public actual typealias HTMLElement = org.w3c.dom.HTMLElement

@Composable
internal actual fun rememberContainerNode(): HTMLElement =
internal actual fun rememberContainerNode(zIndex: String): HTMLElement =
rememberDomNode(parent = document.body!!) {
document.createElement("div").unsafeCast<HTMLElement>().apply {
style.position = "absolute"
style.margin = "0px"
style.zIndex = zIndex
}
}

Expand All @@ -38,7 +39,7 @@ internal actual fun HTMLElement.matchLayout(
internal actual fun <T : HTMLElement> rememberDomNode(parent: HTMLElement, factory: () -> T): T {
return remember(key1 = parent, calculation = factory).also { child ->
DisposableEffect(parent, child) {
parent.insertBefore(child, parent.firstChild)
parent.appendChild(child)
onDispose { parent.removeChild(child) }
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,12 @@ import kotlinx.browser.document
public actual typealias HTMLElement = org.w3c.dom.HTMLElement

@Composable
internal actual fun rememberContainerNode() =
internal actual fun rememberContainerNode(zIndex: String): HTMLElement =
rememberDomNode(parent = document.body!!) {
document.createElement("div").unsafeCast<HTMLElement>().apply {
style.position = "absolute"
style.margin = "0px"
style.zIndex = zIndex
}
}

Expand All @@ -38,7 +39,7 @@ internal actual fun HTMLElement.matchLayout(
internal actual fun <T : HTMLElement> rememberDomNode(parent: HTMLElement, factory: () -> T): T {
return remember(key1 = parent, calculation = factory).also { child ->
DisposableEffect(parent, child) {
parent.insertBefore(child, parent.firstChild)
parent.appendChild(child)
onDispose { parent.removeChild(child) }
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ internal fun WebMapView(

HtmlElement(
modifier = modifier.onGloballyPositioned { maybeMap?.resize() },
// zIndex = "-1", // TODO figure out pointer interop
factory = {
document.createElement("div").unsafeCast<HTMLElement>().apply {
style.apply {
Expand Down

0 comments on commit 18ce6fe

Please sign in to comment.