Skip to content

Commit

Permalink
Merge pull request #51 from huanshankeji/box-with-constraints-react-t…
Browse files Browse the repository at this point in the history
…o-size-changes-js-dom

Fix JS DOM display issues in `BoxWithConstraints` and `com.huanshankeji.compose.material2.ext.TopAppBarScaffold`
  • Loading branch information
ShreckYe authored Dec 20, 2024
2 parents a7ea2bd + d945849 commit d993761
Show file tree
Hide file tree
Showing 6 changed files with 65 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.huanshankeji.compose.foundation

import androidx.compose.runtime.Composable
import androidx.compose.runtime.Stable
import com.huanshankeji.compose.ExperimentalApi
import com.huanshankeji.compose.foundation.layout.BoxScope
import com.huanshankeji.compose.ui.Alignment
import com.huanshankeji.compose.ui.Modifier
Expand All @@ -24,6 +25,7 @@ See https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollTop.
* it applies to the target as a whole on `androidx` targets, but applies to its content on JS DOM.
* For consistency on different platforms, [VerticalScrollBox] is recommended over this modifier.
*/
@ExperimentalApi
expect fun Modifier.verticalScroll(
state: ScrollState
/*
Expand All @@ -37,6 +39,7 @@ expect fun Modifier.verticalScroll(
* For consistency on different platforms, [HorizontalScrollBox] is recommended over this modifier.
* @see verticalScroll
*/
@ExperimentalApi
expect fun Modifier.horizontalScroll(state: ScrollState): Modifier

@Composable
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package com.huanshankeji.compose.ui.unit.ext

import androidx.annotation.IntRange
import com.huanshankeji.compose.ExperimentalApi

// not used yet
@ExperimentalApi
sealed class DpOrPercentage {
class Dp(val dp: androidx.compose.ui.unit.Dp) : DpOrPercentage()
class Percentage(@IntRange(0, 100) val percentage: Int) : DpOrPercentage()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ actual object ScrollState
actual fun Modifier.verticalScroll(state: ScrollState): Modifier =
platformModify { verticalScroll() }


actual fun Modifier.horizontalScroll(state: ScrollState): Modifier =
platformModify { horizontalScroll() }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import com.huanshankeji.compose.foundation.ExperimentalFoundationApi
import com.huanshankeji.compose.foundation.layout.Box
import com.huanshankeji.compose.ui.Alignment
import com.huanshankeji.compose.ui.Modifier
import com.varabyte.kobweb.browser.dom.observers.ResizeObserver
import com.varabyte.kobweb.compose.foundation.layout.BoxScope
import com.varabyte.kobweb.compose.ui.attrsModifier

Expand All @@ -17,16 +18,41 @@ actual fun BoxWithConstraints(
contentAlignment: Alignment,
content: @Composable BoxWithConstraintsScope.() -> Unit
) {
// `DpClientSize.unspecified` instead of null can be used by default to prevent the content from not rendering when `clientSize` is not set
var clientSize by remember { mutableStateOf<ClientSize?>(null) }
// `DivBox` doesn't work here either, so it should not be Kobweb's problem.
Box(
Modifier.platformModify {
attrsModifier {
ref {
clientSize = ClientSize(it.clientWidth, it.clientHeight)
onDispose { clientSize = null }
Modifier.fillMaxSizeStretch()
.platformModify {
attrsModifier {
ref {
//console.log("Initial client size: ${it.clientWidth}, ${it.clientHeight}")
//clientSize = ClientSize(it.clientWidth, it.clientHeight)
val resizeObserver = ResizeObserver { entries, _ ->
val element = entries.single().target

/*
console.log("width: ${element.clientWidth}, height: ${element.clientHeight}")
console.log(entries.first().contentBoxSize.first())
console.log(entries.first().borderBoxSize.first())
console.log(entries.first().devicePixelContentBoxSize.first()) // If there is zoom this one is different from the 2 above.
*/

with(element) {
//console.log("width: $clientWidth, height: $clientHeight")
clientSize = ClientSize(clientWidth, clientHeight)
}
}
resizeObserver.observe(it)

onDispose {
//resizeObserver.unobserve(it)
resizeObserver.disconnect()
clientSize = null
}
}
}
}
}.fillMaxSizeStretch()
.then(modifier),
contentAlignment
) {
Expand All @@ -45,3 +71,13 @@ class BoxWithConstraintsScopeImpl(
) : BoxWithConstraintsScope

private class ClientSize(val clientWidth: Int, val clientHeight: Int)

// removed if not used
/**
* Made in [Dp] so [Dp.Unspecified] can be used.
*/
private class DpClientSize(val clientWidth: Dp, val clientHeight: Dp) {
companion object {
val unspecified = DpClientSize(Dp.Unspecified, Dp.Unspecified)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,8 @@ actual fun TopAppBarScaffold(
actions,
Modifier.weight(1f).fillMaxWidthStretch()
) {
// This part has a lot of nested `Div`s but works. Do not change unless you are sure that expected behavior is not broken.

// The content gets hidden behind the top app bar if this div is not added.
Div({
style {
Expand All @@ -134,9 +136,16 @@ actual fun TopAppBarScaffold(
//overflow(Overflow.Auto) // This seems not needed. TODO remove if confirmed to be not needed
}
}) {
// see `ScaffoldLayoutWithMeasureFix`
val innerPadding = PaddingValues()
content(innerPadding)
// This nested `Div` is here so that a child using `fillMaxSizeStretch` works properly. `fillMaxSizeStretch` seems buggy when used directly in the `position: absolute` parent.
Div({
style {
height(100.percent)
}
}) {
// see `ScaffoldLayoutWithMeasureFix`
val innerPadding = PaddingValues()
content(innerPadding)
}
}

floatingActionButton?.let { fabWithPosition(it) }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,12 @@ actual class ListScope(val mdListScope: MdListScope) {

actual class ItemScope(val mdListItemScope: MdListItemScope)

/*
@Composable
fun PrimitiveList() =
TODO() as Unit
*/

@Composable
actual fun List(
modifier: Modifier,
Expand Down

0 comments on commit d993761

Please sign in to comment.