diff --git a/common/src/commonMain/kotlin/com/huanshankeji/compose/foundation/Scroll.kt b/common/src/commonMain/kotlin/com/huanshankeji/compose/foundation/Scroll.kt index fd772413..f54c430c 100644 --- a/common/src/commonMain/kotlin/com/huanshankeji/compose/foundation/Scroll.kt +++ b/common/src/commonMain/kotlin/com/huanshankeji/compose/foundation/Scroll.kt @@ -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 @@ -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 /* @@ -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 diff --git a/common/src/commonMain/kotlin/com/huanshankeji/compose/ui/unit/ext/DpOrPercentage.kt b/common/src/commonMain/kotlin/com/huanshankeji/compose/ui/unit/ext/DpOrPercentage.kt index c8c64d7f..bf555d9c 100644 --- a/common/src/commonMain/kotlin/com/huanshankeji/compose/ui/unit/ext/DpOrPercentage.kt +++ b/common/src/commonMain/kotlin/com/huanshankeji/compose/ui/unit/ext/DpOrPercentage.kt @@ -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() diff --git a/common/src/jsMain/kotlin/com/huanshankeji/compose/foundation/Scroll.js.kt b/common/src/jsMain/kotlin/com/huanshankeji/compose/foundation/Scroll.js.kt index 6ba45ff1..80a56aab 100644 --- a/common/src/jsMain/kotlin/com/huanshankeji/compose/foundation/Scroll.js.kt +++ b/common/src/jsMain/kotlin/com/huanshankeji/compose/foundation/Scroll.js.kt @@ -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() } diff --git a/common/src/jsMain/kotlin/com/huanshankeji/compose/foundation/layout/ext/BoxWithConstraints.js.kt b/common/src/jsMain/kotlin/com/huanshankeji/compose/foundation/layout/ext/BoxWithConstraints.js.kt index b43dee99..d0807050 100644 --- a/common/src/jsMain/kotlin/com/huanshankeji/compose/foundation/layout/ext/BoxWithConstraints.js.kt +++ b/common/src/jsMain/kotlin/com/huanshankeji/compose/foundation/layout/ext/BoxWithConstraints.js.kt @@ -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 @@ -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(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 ) { @@ -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) + } +} diff --git a/material2/src/jsMain/kotlin/com/huanshankeji/compose/material2/ext/TopAppBarScaffold.js.kt b/material2/src/jsMain/kotlin/com/huanshankeji/compose/material2/ext/TopAppBarScaffold.js.kt index 37852524..37e949aa 100644 --- a/material2/src/jsMain/kotlin/com/huanshankeji/compose/material2/ext/TopAppBarScaffold.js.kt +++ b/material2/src/jsMain/kotlin/com/huanshankeji/compose/material2/ext/TopAppBarScaffold.js.kt @@ -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 { @@ -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) } diff --git a/material3/src/jsMain/kotlin/com/huanshankeji/compose/material3/lazy/ext/List.js.kt b/material3/src/jsMain/kotlin/com/huanshankeji/compose/material3/lazy/ext/List.js.kt index 1182d000..d1567b7e 100644 --- a/material3/src/jsMain/kotlin/com/huanshankeji/compose/material3/lazy/ext/List.js.kt +++ b/material3/src/jsMain/kotlin/com/huanshankeji/compose/material3/lazy/ext/List.js.kt @@ -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,