From c9d4929587f25cfa7124c5eedbe2e0ab1f152aa0 Mon Sep 17 00:00:00 2001 From: Shreck Ye Date: Fri, 9 Dec 2022 20:38:39 +0800 Subject: [PATCH 01/34] Add `modifierOrAttrs` arguments for the existing Material composables --- .../src/main/kotlin/VersionsAndDependencies.kt | 3 +++ .../main/kotlin/common-conventions.gradle.kts | 1 + compose-multiplatform-common/build.gradle.kts | 2 ++ .../com/huanshankeji/compose/material/Button.kt | 10 +++++++++- .../com/huanshankeji/compose/material/Card.kt | 6 +++++- .../com/huanshankeji/compose/material/Icon.kt | 6 +++++- .../huanshankeji/compose/material/IconButton.kt | 10 +++++++++- .../com/huanshankeji/compose/material/Button.kt | 17 +++++++++++++++-- .../com/huanshankeji/compose/material/Card.kt | 9 +++++++-- .../com/huanshankeji/compose/material/Icon.kt | 9 +++++++-- .../huanshankeji/compose/material/IconButton.kt | 17 ++++++++++++++--- .../com/huanshankeji/compose/material/Button.kt | 13 +++++++++++-- .../com/huanshankeji/compose/material/Card.kt | 9 +++++++-- .../com/huanshankeji/compose/material/Icon.kt | 9 +++++++-- .../huanshankeji/compose/material/IconButton.kt | 13 +++++++++++-- .../compose/material/TopAppBarScaffold.kt | 4 ++-- .../compose/material/demo/Composables.kt | 8 ++++---- 17 files changed, 119 insertions(+), 27 deletions(-) create mode 100644 buildSrc/src/main/kotlin/VersionsAndDependencies.kt diff --git a/buildSrc/src/main/kotlin/VersionsAndDependencies.kt b/buildSrc/src/main/kotlin/VersionsAndDependencies.kt new file mode 100644 index 00000000..5dc220f5 --- /dev/null +++ b/buildSrc/src/main/kotlin/VersionsAndDependencies.kt @@ -0,0 +1,3 @@ +object DependencyVersions { + val huanshankejiComposeWeb = "0.1.1-SNAPSHOT" +} diff --git a/buildSrc/src/main/kotlin/common-conventions.gradle.kts b/buildSrc/src/main/kotlin/common-conventions.gradle.kts index 931c4468..2a1656af 100644 --- a/buildSrc/src/main/kotlin/common-conventions.gradle.kts +++ b/buildSrc/src/main/kotlin/common-conventions.gradle.kts @@ -4,6 +4,7 @@ plugins { } repositories { + mavenLocal() mavenCentral() maven("https://maven.pkg.jetbrains.space/public/p/compose/dev") google() diff --git a/compose-multiplatform-common/build.gradle.kts b/compose-multiplatform-common/build.gradle.kts index 5b453472..b60395a3 100644 --- a/compose-multiplatform-common/build.gradle.kts +++ b/compose-multiplatform-common/build.gradle.kts @@ -17,6 +17,8 @@ kotlin { named("jsMain") { dependencies { implementation(compose.web.core) + + api("com.huanshankeji:compose-web-common:${DependencyVersions.huanshankejiComposeWeb}") } } } diff --git a/compose-multiplatform-material/src/commonMain/kotlin/com/huanshankeji/compose/material/Button.kt b/compose-multiplatform-material/src/commonMain/kotlin/com/huanshankeji/compose/material/Button.kt index 0625a304..b2ba102a 100644 --- a/compose-multiplatform-material/src/commonMain/kotlin/com/huanshankeji/compose/material/Button.kt +++ b/compose-multiplatform-material/src/commonMain/kotlin/com/huanshankeji/compose/material/Button.kt @@ -1,11 +1,19 @@ package com.huanshankeji.compose.material import androidx.compose.runtime.Composable +import com.huanshankeji.compose.ui.Element +import com.huanshankeji.compose.ui.ModifierOrAttrs expect /*value*/ class ButtonScope { @Composable fun Label(text: String) } +expect abstract class ButtonElement : Element + @Composable -expect fun Button(onClick: () -> Unit, content: @Composable ButtonScope.() -> Unit) +expect fun Button( + onClick: () -> Unit, + modifierOrAttrs: ModifierOrAttrs = null, + content: @Composable ButtonScope.() -> Unit +) diff --git a/compose-multiplatform-material/src/commonMain/kotlin/com/huanshankeji/compose/material/Card.kt b/compose-multiplatform-material/src/commonMain/kotlin/com/huanshankeji/compose/material/Card.kt index f990dbb6..ae232b3a 100644 --- a/compose-multiplatform-material/src/commonMain/kotlin/com/huanshankeji/compose/material/Card.kt +++ b/compose-multiplatform-material/src/commonMain/kotlin/com/huanshankeji/compose/material/Card.kt @@ -1,6 +1,10 @@ package com.huanshankeji.compose.material import androidx.compose.runtime.Composable +import com.huanshankeji.compose.ui.Element +import com.huanshankeji.compose.ui.ModifierOrAttrs + +expect abstract class CardElement : Element @Composable -expect fun Card(content: @Composable () -> Unit) +expect fun Card(modifierOrAttrs: ModifierOrAttrs = null, content: @Composable () -> Unit) diff --git a/compose-multiplatform-material/src/commonMain/kotlin/com/huanshankeji/compose/material/Icon.kt b/compose-multiplatform-material/src/commonMain/kotlin/com/huanshankeji/compose/material/Icon.kt index e9244067..b0576f0a 100644 --- a/compose-multiplatform-material/src/commonMain/kotlin/com/huanshankeji/compose/material/Icon.kt +++ b/compose-multiplatform-material/src/commonMain/kotlin/com/huanshankeji/compose/material/Icon.kt @@ -2,6 +2,10 @@ package com.huanshankeji.compose.material import androidx.compose.runtime.Composable import com.huanshankeji.compose.material.icon.MaterialIcon +import com.huanshankeji.compose.ui.Element +import com.huanshankeji.compose.ui.ModifierOrAttrs + +expect abstract class IconElement : Element @Composable -expect fun Icon(materialIcon: MaterialIcon) +expect fun Icon(materialIcon: MaterialIcon, modifierOrAttrs: ModifierOrAttrs = null) diff --git a/compose-multiplatform-material/src/commonMain/kotlin/com/huanshankeji/compose/material/IconButton.kt b/compose-multiplatform-material/src/commonMain/kotlin/com/huanshankeji/compose/material/IconButton.kt index ac28f796..033d7a58 100644 --- a/compose-multiplatform-material/src/commonMain/kotlin/com/huanshankeji/compose/material/IconButton.kt +++ b/compose-multiplatform-material/src/commonMain/kotlin/com/huanshankeji/compose/material/IconButton.kt @@ -1,6 +1,14 @@ package com.huanshankeji.compose.material import androidx.compose.runtime.Composable +import com.huanshankeji.compose.ui.Element +import com.huanshankeji.compose.ui.ModifierOrAttrs + +expect abstract class IconButtonElement : Element @Composable -expect fun IconButton(onClick: () -> Unit, content: @Composable () -> Unit) +expect fun IconButton( + onClick: () -> Unit, + modifierOrAttrs: ModifierOrAttrs = null, + content: @Composable () -> Unit +) diff --git a/compose-multiplatform-material/src/jsMain/kotlin/com/huanshankeji/compose/material/Button.kt b/compose-multiplatform-material/src/jsMain/kotlin/com/huanshankeji/compose/material/Button.kt index d95a982f..38c0878d 100644 --- a/compose-multiplatform-material/src/jsMain/kotlin/com/huanshankeji/compose/material/Button.kt +++ b/compose-multiplatform-material/src/jsMain/kotlin/com/huanshankeji/compose/material/Button.kt @@ -1,6 +1,10 @@ package com.huanshankeji.compose.material import androidx.compose.runtime.Composable +import com.huanshankeji.compose.ui.ModifierOrAttrs +import com.huanshankeji.compose.ui.toAttrs +import com.huanshankeji.compose.web.attributes.attrs +import com.huanshankeji.compose.web.attributes.plus import dev.petuska.kmdc.button.Label import dev.petuska.kmdc.button.MDCButton import dev.petuska.kmdc.button.MDCButtonScope @@ -12,6 +16,15 @@ actual class ButtonScope(val mdcButtonScope: MDCButtonScope) mdcButtonScope.Label(text) } +actual typealias ButtonElement = HTMLButtonElement + @Composable -actual fun Button(onClick: () -> Unit, content: @Composable ButtonScope.() -> Unit) = - MDCButton(attrs = { onClick { onClick() } }) { ButtonScope(this).content() } +actual fun Button( + onClick: () -> Unit, modifierOrAttrs: ModifierOrAttrs, content: @Composable ButtonScope.() -> Unit +) = + MDCButton(attrs = attrs { + onClick { onClick() } + } + modifierOrAttrs.toAttrs()) { + ButtonScope(this).content() + } + diff --git a/compose-multiplatform-material/src/jsMain/kotlin/com/huanshankeji/compose/material/Card.kt b/compose-multiplatform-material/src/jsMain/kotlin/com/huanshankeji/compose/material/Card.kt index 338661db..1e5f9d68 100644 --- a/compose-multiplatform-material/src/jsMain/kotlin/com/huanshankeji/compose/material/Card.kt +++ b/compose-multiplatform-material/src/jsMain/kotlin/com/huanshankeji/compose/material/Card.kt @@ -1,8 +1,13 @@ package com.huanshankeji.compose.material import androidx.compose.runtime.Composable +import com.huanshankeji.compose.ui.ModifierOrAttrs +import com.huanshankeji.compose.ui.toAttrs import dev.petuska.kmdc.card.MDCCard +import org.w3c.dom.HTMLDivElement + +actual typealias CardElement = HTMLDivElement @Composable -actual fun Card(content: @Composable () -> Unit) = - MDCCard { content() } +actual fun Card(modifierOrAttrs: ModifierOrAttrs, content: @Composable () -> Unit) = + MDCCard(attrs = modifierOrAttrs.toAttrs()) { content() } diff --git a/compose-multiplatform-material/src/jsMain/kotlin/com/huanshankeji/compose/material/Icon.kt b/compose-multiplatform-material/src/jsMain/kotlin/com/huanshankeji/compose/material/Icon.kt index 7cbc6d03..29e344f0 100644 --- a/compose-multiplatform-material/src/jsMain/kotlin/com/huanshankeji/compose/material/Icon.kt +++ b/compose-multiplatform-material/src/jsMain/kotlin/com/huanshankeji/compose/material/Icon.kt @@ -2,11 +2,16 @@ package com.huanshankeji.compose.material import androidx.compose.runtime.Composable import com.huanshankeji.compose.material.icon.MaterialIcon +import com.huanshankeji.compose.ui.ModifierOrAttrs +import com.huanshankeji.compose.ui.toAttrs import dev.petuska.kmdcx.icons.MDCIconSpan +import org.w3c.dom.HTMLSpanElement + +actual typealias IconElement = HTMLSpanElement /** * There is often a better alternative of adding the CSS rule to the parent element to using this composable directly. */ @Composable -actual fun Icon(materialIcon: MaterialIcon) = - MDCIconSpan(materialIcon.mdcIcon) +actual fun Icon(materialIcon: MaterialIcon, modifierOrAttrs: ModifierOrAttrs) = + MDCIconSpan(materialIcon.mdcIcon, attrs = modifierOrAttrs.toAttrs()) diff --git a/compose-multiplatform-material/src/jsMain/kotlin/com/huanshankeji/compose/material/IconButton.kt b/compose-multiplatform-material/src/jsMain/kotlin/com/huanshankeji/compose/material/IconButton.kt index 1bff16cb..0c343bf6 100644 --- a/compose-multiplatform-material/src/jsMain/kotlin/com/huanshankeji/compose/material/IconButton.kt +++ b/compose-multiplatform-material/src/jsMain/kotlin/com/huanshankeji/compose/material/IconButton.kt @@ -1,10 +1,21 @@ package com.huanshankeji.compose.material import androidx.compose.runtime.Composable +import com.huanshankeji.compose.ui.ModifierOrAttrs +import com.huanshankeji.compose.ui.toAttrs +import com.huanshankeji.compose.web.attributes.attrs +import com.huanshankeji.compose.web.attributes.plus import dev.petuska.kmdc.icon.button.MDCIconButton +import org.w3c.dom.HTMLButtonElement + +actual typealias IconButtonElement = HTMLButtonElement @Composable -actual fun IconButton(onClick: () -> Unit, content: @Composable () -> Unit) = - MDCIconButton(attrs = { +actual fun IconButton( + onClick: () -> Unit, + modifierOrAttrs: ModifierOrAttrs, + content: @Composable () -> Unit +) = + MDCIconButton(attrs = attrs { onClick { onClick() } - }) { content() } + } + modifierOrAttrs.toAttrs()) { content() } diff --git a/compose-multiplatform-material/src/jvmMain/kotlin/com/huanshankeji/compose/material/Button.kt b/compose-multiplatform-material/src/jvmMain/kotlin/com/huanshankeji/compose/material/Button.kt index afb79103..abb78391 100644 --- a/compose-multiplatform-material/src/jvmMain/kotlin/com/huanshankeji/compose/material/Button.kt +++ b/compose-multiplatform-material/src/jvmMain/kotlin/com/huanshankeji/compose/material/Button.kt @@ -2,6 +2,9 @@ package com.huanshankeji.compose.material import androidx.compose.foundation.layout.RowScope import androidx.compose.runtime.Composable +import com.huanshankeji.compose.ui.Element +import com.huanshankeji.compose.ui.ModifierOrAttrs +import com.huanshankeji.compose.ui.toModifier actual class ButtonScope(val rowScope: RowScope) { @Composable @@ -9,6 +12,12 @@ actual class ButtonScope(val rowScope: RowScope) { androidx.compose.material.Text(text) } +actual abstract class ButtonElement : Element() + @Composable -actual fun Button(onClick: () -> Unit, content: @Composable ButtonScope.() -> Unit) = - androidx.compose.material.Button(onClick) { ButtonScope(this).content() } +actual fun Button( + onClick: () -> Unit, + modifierOrAttrs: ModifierOrAttrs, + content: @Composable ButtonScope.() -> Unit +) = + androidx.compose.material.Button(onClick, modifierOrAttrs.toModifier()) { ButtonScope(this).content() } diff --git a/compose-multiplatform-material/src/jvmMain/kotlin/com/huanshankeji/compose/material/Card.kt b/compose-multiplatform-material/src/jvmMain/kotlin/com/huanshankeji/compose/material/Card.kt index 5eb6d539..fa6fc175 100644 --- a/compose-multiplatform-material/src/jvmMain/kotlin/com/huanshankeji/compose/material/Card.kt +++ b/compose-multiplatform-material/src/jvmMain/kotlin/com/huanshankeji/compose/material/Card.kt @@ -1,7 +1,12 @@ package com.huanshankeji.compose.material import androidx.compose.runtime.Composable +import com.huanshankeji.compose.ui.Element +import com.huanshankeji.compose.ui.ModifierOrAttrs +import com.huanshankeji.compose.ui.toModifier + +actual abstract class CardElement : Element() @Composable -actual fun Card(content: @Composable () -> Unit) = - androidx.compose.material.Card { content() } +actual fun Card(modifierOrAttrs: ModifierOrAttrs, content: @Composable () -> Unit) = + androidx.compose.material.Card(modifierOrAttrs.toModifier()) { content() } diff --git a/compose-multiplatform-material/src/jvmMain/kotlin/com/huanshankeji/compose/material/Icon.kt b/compose-multiplatform-material/src/jvmMain/kotlin/com/huanshankeji/compose/material/Icon.kt index 629ed65e..2a884765 100644 --- a/compose-multiplatform-material/src/jvmMain/kotlin/com/huanshankeji/compose/material/Icon.kt +++ b/compose-multiplatform-material/src/jvmMain/kotlin/com/huanshankeji/compose/material/Icon.kt @@ -2,8 +2,13 @@ package com.huanshankeji.compose.material import androidx.compose.runtime.Composable import com.huanshankeji.compose.material.icon.MaterialIcon +import com.huanshankeji.compose.ui.Element +import com.huanshankeji.compose.ui.ModifierOrAttrs +import com.huanshankeji.compose.ui.toModifier + +actual abstract class IconElement : Element() @Composable -actual fun Icon(materialIcon: MaterialIcon) = - androidx.compose.material.Icon(materialIcon, null) +actual fun Icon(materialIcon: MaterialIcon, modifierOrAttrs: ModifierOrAttrs) = + androidx.compose.material.Icon(materialIcon, null, modifierOrAttrs.toModifier()) // no `contentDescription` for now diff --git a/compose-multiplatform-material/src/jvmMain/kotlin/com/huanshankeji/compose/material/IconButton.kt b/compose-multiplatform-material/src/jvmMain/kotlin/com/huanshankeji/compose/material/IconButton.kt index bea1a08e..222cbe04 100644 --- a/compose-multiplatform-material/src/jvmMain/kotlin/com/huanshankeji/compose/material/IconButton.kt +++ b/compose-multiplatform-material/src/jvmMain/kotlin/com/huanshankeji/compose/material/IconButton.kt @@ -1,7 +1,16 @@ package com.huanshankeji.compose.material import androidx.compose.runtime.Composable +import com.huanshankeji.compose.ui.Element +import com.huanshankeji.compose.ui.ModifierOrAttrs +import com.huanshankeji.compose.ui.toModifier + +actual abstract class IconButtonElement : Element() @Composable -actual fun IconButton(onClick: () -> Unit, content: @Composable () -> Unit) = - androidx.compose.material.IconButton(onClick = onClick, content = content) +actual fun IconButton( + onClick: () -> Unit, + modifierOrAttrs: ModifierOrAttrs, + content: @Composable () -> Unit +) = + androidx.compose.material.IconButton(onClick, modifierOrAttrs.toModifier(), content = content) diff --git a/compose-multiplatform-material/src/jvmMain/kotlin/com/huanshankeji/compose/material/TopAppBarScaffold.kt b/compose-multiplatform-material/src/jvmMain/kotlin/com/huanshankeji/compose/material/TopAppBarScaffold.kt index e059b6e7..00e3782e 100644 --- a/compose-multiplatform-material/src/jvmMain/kotlin/com/huanshankeji/compose/material/TopAppBarScaffold.kt +++ b/compose-multiplatform-material/src/jvmMain/kotlin/com/huanshankeji/compose/material/TopAppBarScaffold.kt @@ -9,7 +9,7 @@ import com.huanshankeji.compose.material.icon.MaterialIcon actual class NavigationIconScope private constructor() { @Composable actual fun NavButton(onClick: () -> Unit, content: @Composable () -> Unit) = - IconButton(onClick, content) + IconButton(onClick, content = content) @Composable actual fun MaterialIconNavButton(onClick: () -> Unit, materialIcon: MaterialIcon) = @@ -23,7 +23,7 @@ actual class NavigationIconScope private constructor() { actual class TopAppBarActionsScope(val rowScope: RowScope) { @Composable actual fun ActionButton(onClick: () -> Unit, content: @Composable () -> Unit) = - IconButton(onClick, content) + IconButton(onClick, content = content) @Composable actual fun MaterialIconActionButton(onClick: () -> Unit, materialIcon: MaterialIcon) = diff --git a/demo/src/commonMain/kotlin/com/huanshankeji/compose/material/demo/Composables.kt b/demo/src/commonMain/kotlin/com/huanshankeji/compose/material/demo/Composables.kt index de2fb4ca..3162e2bd 100644 --- a/demo/src/commonMain/kotlin/com/huanshankeji/compose/material/demo/Composables.kt +++ b/demo/src/commonMain/kotlin/com/huanshankeji/compose/material/demo/Composables.kt @@ -3,10 +3,7 @@ package com.huanshankeji.compose.material.demo import androidx.compose.runtime.* import com.huanshankeji.compose.BasicText import com.huanshankeji.compose.layout.Box -import com.huanshankeji.compose.material.Button -import com.huanshankeji.compose.material.Card -import com.huanshankeji.compose.material.Text -import com.huanshankeji.compose.material.TopAppBarScaffold +import com.huanshankeji.compose.material.* import com.huanshankeji.compose.material.icon.MaterialIcons import com.huanshankeji.compose.ui.unit.dpOrPx @@ -32,6 +29,9 @@ fun App() { Button({ count++ }) { Label(count.toString()) } + IconButton({ count++ }) { + Icon(MaterialIcons.Search) + } } } } From 815da59e57b67ba1071d070d32d4f48dc6bcb9c5 Mon Sep 17 00:00:00 2001 From: Shreck Ye Date: Fri, 9 Dec 2022 21:29:29 +0800 Subject: [PATCH 02/34] Add an `IconButton` that takes a `MaterialIcon` --- .../com/huanshankeji/compose/material/IconButton.kt | 11 +++++++++++ .../material/{IconButton.kt => IconButtonJvm.kt} | 0 .../huanshankeji/compose/material/demo/Composables.kt | 8 ++++---- 3 files changed, 15 insertions(+), 4 deletions(-) rename compose-multiplatform-material/src/jvmMain/kotlin/com/huanshankeji/compose/material/{IconButton.kt => IconButtonJvm.kt} (100%) diff --git a/compose-multiplatform-material/src/commonMain/kotlin/com/huanshankeji/compose/material/IconButton.kt b/compose-multiplatform-material/src/commonMain/kotlin/com/huanshankeji/compose/material/IconButton.kt index 033d7a58..6395c2a4 100644 --- a/compose-multiplatform-material/src/commonMain/kotlin/com/huanshankeji/compose/material/IconButton.kt +++ b/compose-multiplatform-material/src/commonMain/kotlin/com/huanshankeji/compose/material/IconButton.kt @@ -1,6 +1,7 @@ package com.huanshankeji.compose.material import androidx.compose.runtime.Composable +import com.huanshankeji.compose.material.icon.MaterialIcon import com.huanshankeji.compose.ui.Element import com.huanshankeji.compose.ui.ModifierOrAttrs @@ -12,3 +13,13 @@ expect fun IconButton( modifierOrAttrs: ModifierOrAttrs = null, content: @Composable () -> Unit ) + + +@Composable +fun IconButton( + onClick: () -> Unit, + modifierOrAttrs: ModifierOrAttrs = null, + materialIcon: MaterialIcon +) = + IconButton(onClick, modifierOrAttrs) { Icon(materialIcon) } + diff --git a/compose-multiplatform-material/src/jvmMain/kotlin/com/huanshankeji/compose/material/IconButton.kt b/compose-multiplatform-material/src/jvmMain/kotlin/com/huanshankeji/compose/material/IconButtonJvm.kt similarity index 100% rename from compose-multiplatform-material/src/jvmMain/kotlin/com/huanshankeji/compose/material/IconButton.kt rename to compose-multiplatform-material/src/jvmMain/kotlin/com/huanshankeji/compose/material/IconButtonJvm.kt diff --git a/demo/src/commonMain/kotlin/com/huanshankeji/compose/material/demo/Composables.kt b/demo/src/commonMain/kotlin/com/huanshankeji/compose/material/demo/Composables.kt index 3162e2bd..70005f9b 100644 --- a/demo/src/commonMain/kotlin/com/huanshankeji/compose/material/demo/Composables.kt +++ b/demo/src/commonMain/kotlin/com/huanshankeji/compose/material/demo/Composables.kt @@ -26,12 +26,12 @@ fun App() { Text("Material text") var count by remember { mutableStateOf(0) } - Button({ count++ }) { + val onClick: () -> Unit = { count++ } + Button(onClick) { Label(count.toString()) } - IconButton({ count++ }) { - Icon(MaterialIcons.Search) - } + + IconButton(onClick, materialIcon = MaterialIcons.Search) } } } From a2139e32e0a757ea612706b60de0db7c739b835f Mon Sep 17 00:00:00 2001 From: Shreck Ye Date: Sat, 10 Dec 2022 01:15:05 +0800 Subject: [PATCH 03/34] Bump `compose-web-common` to `0.2.0-SNAPSHOT` --- buildSrc/src/main/kotlin/VersionsAndDependencies.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buildSrc/src/main/kotlin/VersionsAndDependencies.kt b/buildSrc/src/main/kotlin/VersionsAndDependencies.kt index 5dc220f5..bd01fb62 100644 --- a/buildSrc/src/main/kotlin/VersionsAndDependencies.kt +++ b/buildSrc/src/main/kotlin/VersionsAndDependencies.kt @@ -1,3 +1,3 @@ object DependencyVersions { - val huanshankejiComposeWeb = "0.1.1-SNAPSHOT" + val huanshankejiComposeWeb = "0.2.0-SNAPSHOT" } From 55844690c14d0549ba2a45d1c33a7bbbfd286fb0 Mon Sep 17 00:00:00 2001 From: Shreck Ye Date: Sun, 11 Dec 2022 01:40:15 +0800 Subject: [PATCH 04/34] Add some `compileOnly` dependencies for KDoc references and add an initial and untested implementation of `List` --- compose-multiplatform-common/build.gradle.kts | 1 + .../compose/ui/ModifierOrAttrsScope.kt | 3 +- .../build.gradle.kts | 1 + .../compose/material/ListAndLazyColumn.kt | 41 ++++++++++ .../compose/material/ListAndLazyColumn.kt | 81 +++++++++++++++++++ .../compose/material/ListAndLazyColumnJvm.kt | 44 ++++++++++ gradle.properties | 2 + 7 files changed, 172 insertions(+), 1 deletion(-) create mode 100644 compose-multiplatform-material/src/commonMain/kotlin/com/huanshankeji/compose/material/ListAndLazyColumn.kt create mode 100644 compose-multiplatform-material/src/jsMain/kotlin/com/huanshankeji/compose/material/ListAndLazyColumn.kt create mode 100644 compose-multiplatform-material/src/jvmMain/kotlin/com/huanshankeji/compose/material/ListAndLazyColumnJvm.kt create mode 100644 gradle.properties diff --git a/compose-multiplatform-common/build.gradle.kts b/compose-multiplatform-common/build.gradle.kts index b60395a3..bb4168d0 100644 --- a/compose-multiplatform-common/build.gradle.kts +++ b/compose-multiplatform-common/build.gradle.kts @@ -7,6 +7,7 @@ kotlin { named("commonMain") { dependencies { implementation(compose.runtime) + compileOnly(compose.foundation) // for KDoc element links only } } named("jvmMain") { diff --git a/compose-multiplatform-common/src/commonMain/kotlin/com/huanshankeji/compose/ui/ModifierOrAttrsScope.kt b/compose-multiplatform-common/src/commonMain/kotlin/com/huanshankeji/compose/ui/ModifierOrAttrsScope.kt index ae85ddd2..4c5117b3 100644 --- a/compose-multiplatform-common/src/commonMain/kotlin/com/huanshankeji/compose/ui/ModifierOrAttrsScope.kt +++ b/compose-multiplatform-common/src/commonMain/kotlin/com/huanshankeji/compose/ui/ModifierOrAttrsScope.kt @@ -1,5 +1,6 @@ package com.huanshankeji.compose.ui +//import androidx.compose.ui.Modifier import com.huanshankeji.compose.ui.unit.SizeValue typealias ModifierOrAttrs = (ModifierOrAttrsScope.() -> Unit)? @@ -14,7 +15,7 @@ expect class StyleScope { } /* -/** An alternative immutable design like `Modifier`. */ +/** An alternative immutable design like [Modifier]. */ expect class ModifierOrAttrsImmutable { fun padding(): ModifierOrAttrsImmutable } diff --git a/compose-multiplatform-material/build.gradle.kts b/compose-multiplatform-material/build.gradle.kts index 7ceb074c..fd7bae21 100644 --- a/compose-multiplatform-material/build.gradle.kts +++ b/compose-multiplatform-material/build.gradle.kts @@ -8,6 +8,7 @@ kotlin { dependencies { implementation(compose.runtime) api(project(":compose-multiplatform-common")) + compileOnly(compose.material) // for KDoc element links only } } // TODO: a `jvmCommon` source set to share code for `jvm`/`desktop` and `android` diff --git a/compose-multiplatform-material/src/commonMain/kotlin/com/huanshankeji/compose/material/ListAndLazyColumn.kt b/compose-multiplatform-material/src/commonMain/kotlin/com/huanshankeji/compose/material/ListAndLazyColumn.kt new file mode 100644 index 00000000..31e8d3bd --- /dev/null +++ b/compose-multiplatform-material/src/commonMain/kotlin/com/huanshankeji/compose/material/ListAndLazyColumn.kt @@ -0,0 +1,41 @@ +package com.huanshankeji.compose.material + +import androidx.compose.foundation.lazy.LazyListScope +import androidx.compose.runtime.Composable +import com.huanshankeji.compose.ui.Element +import com.huanshankeji.compose.ui.ModifierOrAttrs + +expect abstract class ListElement : Element + +/** @see LazyListScope */ +expect class ListScope { + fun item(key: Any? = null, contentType: Any? = null, content: @Composable ItemScope.() -> Unit) + + fun items( + count: Int, + key: ((index: Int) -> Any)? = null, + contentType: (index: Int) -> Any? = { null }, + itemContent: @Composable ItemScope.(index: Int) -> Unit + ) + + fun group( + key: Any? = null, + contentType: Any? = null, + headerContent: @Composable HeaderScope.() -> Unit, + content: ListScope.() -> Unit + ) +} + +expect class ItemScope +expect class HeaderScope + +@Composable +expect fun List(modifierOrAttrs: ModifierOrAttrs = null, content: ListScope.() -> Unit) + +/** + * An alias for [List] that follows the name of [androidx.compose.foundation.lazy.LazyColumn]. + * The current implementation is not actually lazy on web. + */ +@Composable +fun LazyColumn(modifierOrAttrs: ModifierOrAttrs = null, content: ListScope.() -> Unit) = + List(modifierOrAttrs, content) diff --git a/compose-multiplatform-material/src/jsMain/kotlin/com/huanshankeji/compose/material/ListAndLazyColumn.kt b/compose-multiplatform-material/src/jsMain/kotlin/com/huanshankeji/compose/material/ListAndLazyColumn.kt new file mode 100644 index 00000000..ac91e0b5 --- /dev/null +++ b/compose-multiplatform-material/src/jsMain/kotlin/com/huanshankeji/compose/material/ListAndLazyColumn.kt @@ -0,0 +1,81 @@ +package com.huanshankeji.compose.material + +import androidx.compose.runtime.Composable +import com.huanshankeji.compose.ui.ModifierOrAttrs +import com.huanshankeji.compose.ui.toAttrs +import dev.petuska.kmdc.list.MDCList +import dev.petuska.kmdc.list.MDCListGroup +import dev.petuska.kmdc.list.MDCListScope +import dev.petuska.kmdc.list.Subheader +import dev.petuska.kmdc.list.item.ListItem +import dev.petuska.kmdc.list.item.MDCListItemScope +import org.jetbrains.compose.web.dom.ElementScope +import org.w3c.dom.HTMLHeadingElement +import org.w3c.dom.HTMLLIElement +import org.w3c.dom.HTMLUListElement + +actual typealias ListElement = HTMLUListElement + +/** + * This class contains mutable fields. + * @see androidx.compose.foundation.lazy.LazyListScopeImpl + */ +actual class ListScope( + val mdcListScope: MDCListScope +) { + private var composables: MutableList<@Composable () -> Unit>? = null + private fun addComposable(composable: @Composable () -> Unit) { + composables!!.add(composable) + } + + /** Add the composable functions with the non-composable functions and then invoke them. */ + @Composable + fun ComposableRun(content: ListScope.() -> Unit) { + composables = mutableListOf() + content() + for (composable in composables!!) + composable() + composables = null + } + + + actual fun item(key: Any?, contentType: Any?, content: @Composable ItemScope.() -> Unit) = addComposable { + mdcListScope.ListItem { ItemScope(this).content() } + } + + actual fun items( + count: Int, + key: ((index: Int) -> Any)?, + contentType: (index: Int) -> Any?, + itemContent: @Composable ItemScope.(index: Int) -> Unit + ) = addComposable { + repeat(count) { i -> + mdcListScope.ListItem { ItemScope(this).itemContent(i) } + } + } + + actual fun group( + key: Any?, + contentType: Any?, + headerContent: @Composable HeaderScope.() -> Unit, + content: ListScope.() -> Unit + ) = addComposable { + MDCListGroup { + Subheader { + HeaderScope(this).headerContent() + } + MDCList { + ListScope(this).ComposableRun(content) + } + } + } +} + +actual class ItemScope(val mdcListScope: MDCListItemScope) +actual class HeaderScope(val htmlHeadingElementScope: ElementScope) + +@Composable +actual fun List(modifierOrAttrs: ModifierOrAttrs, content: ListScope.() -> Unit) = + MDCList(attrs = modifierOrAttrs.toAttrs()) { + ListScope(this).ComposableRun(content) + } diff --git a/compose-multiplatform-material/src/jvmMain/kotlin/com/huanshankeji/compose/material/ListAndLazyColumnJvm.kt b/compose-multiplatform-material/src/jvmMain/kotlin/com/huanshankeji/compose/material/ListAndLazyColumnJvm.kt new file mode 100644 index 00000000..4176b579 --- /dev/null +++ b/compose-multiplatform-material/src/jvmMain/kotlin/com/huanshankeji/compose/material/ListAndLazyColumnJvm.kt @@ -0,0 +1,44 @@ +package com.huanshankeji.compose.material + +import androidx.compose.foundation.ExperimentalFoundationApi +import androidx.compose.foundation.lazy.LazyItemScope +import androidx.compose.foundation.lazy.LazyListScope +import androidx.compose.runtime.Composable +import com.huanshankeji.compose.ui.Element +import com.huanshankeji.compose.ui.ModifierOrAttrs +import com.huanshankeji.compose.ui.toModifier + +actual abstract class ListElement : Element() + +actual class ListScope(val lazyListScope: LazyListScope) { + actual fun item(key: Any?, contentType: Any?, content: @Composable ItemScope.() -> Unit) = + lazyListScope.item(key, contentType) { ItemScope(this).content() } + + actual fun items( + count: Int, + key: ((index: Int) -> Any)?, + contentType: (index: Int) -> Any?, + itemContent: @Composable ItemScope.(index: Int) -> Unit + ) = + lazyListScope.items(count, key, contentType) { ItemScope(this).itemContent(it) } + + @OptIn(ExperimentalFoundationApi::class) + actual fun group( + key: Any?, + contentType: Any?, + headerContent: @Composable HeaderScope.() -> Unit, + content: ListScope.() -> Unit + ) { + lazyListScope.stickyHeader(key, contentType) { HeaderScope(this).headerContent() } + content() + } +} + +actual class ItemScope(val lazyItemScope: LazyItemScope) +actual typealias HeaderScope = ItemScope + +@Composable +actual fun List(modifierOrAttrs: ModifierOrAttrs, content: ListScope.() -> Unit) = + androidx.compose.foundation.lazy.LazyColumn(modifierOrAttrs.toModifier()) { + ListScope(this).content() + } diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 00000000..cae61f9b --- /dev/null +++ b/gradle.properties @@ -0,0 +1,2 @@ +# for KDoc element links only +org.jetbrains.compose.experimental.jscanvas.enabled=true From d0a6ba0cc861edf13a41757981b95331d1427921 Mon Sep 17 00:00:00 2001 From: Shreck Ye Date: Sun, 11 Dec 2022 12:34:20 +0800 Subject: [PATCH 05/34] Update README.md --- README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/README.md b/README.md index 94e654f2..39297a73 100644 --- a/README.md +++ b/README.md @@ -4,8 +4,6 @@ Some simple Compose Multiplatform Material Design component wrappers for desktop We try to make the styles of the composable components follow those of the desktop and Android ones in `com.huanshankeji.compose.material`, meanwhile being compatible with the Web APIs. However, only a subset of the composable arguments is supported due to the API differences and limitations of the web composables this project depends on. -Customizing styles (using `Modifier`s for desktop and Android, and `attrs: AttrBuilderContext<*>?` for web) is not supported yet. - Visual consistency across different platforms is not guaranteed. There is no documentation for this project yet. Check out the demo project on how to use the components. From b863a683bae1b67d60ba304f9b2e7d2d82e16785 Mon Sep 17 00:00:00 2001 From: Shreck Ye Date: Sun, 11 Dec 2022 16:20:45 +0800 Subject: [PATCH 06/34] Add `contentDescription` for icons --- .../com/huanshankeji/compose/material/Icon.kt | 4 +++- .../compose/material/TopAppBarScaffold.kt | 4 ++-- .../com/huanshankeji/compose/material/Icon.kt | 20 +++++++++++++++++-- .../compose/material/TopAppBarScaffold.kt | 18 ++++++++++------- .../com/huanshankeji/compose/material/Icon.kt | 7 ++++--- .../compose/material/TopAppBarScaffold.kt | 8 ++++---- 6 files changed, 42 insertions(+), 19 deletions(-) diff --git a/compose-multiplatform-material/src/commonMain/kotlin/com/huanshankeji/compose/material/Icon.kt b/compose-multiplatform-material/src/commonMain/kotlin/com/huanshankeji/compose/material/Icon.kt index b0576f0a..78976655 100644 --- a/compose-multiplatform-material/src/commonMain/kotlin/com/huanshankeji/compose/material/Icon.kt +++ b/compose-multiplatform-material/src/commonMain/kotlin/com/huanshankeji/compose/material/Icon.kt @@ -8,4 +8,6 @@ import com.huanshankeji.compose.ui.ModifierOrAttrs expect abstract class IconElement : Element @Composable -expect fun Icon(materialIcon: MaterialIcon, modifierOrAttrs: ModifierOrAttrs = null) +expect fun Icon( + materialIcon: MaterialIcon, contentDescription: String?, modifierOrAttrs: ModifierOrAttrs = null +) diff --git a/compose-multiplatform-material/src/commonMain/kotlin/com/huanshankeji/compose/material/TopAppBarScaffold.kt b/compose-multiplatform-material/src/commonMain/kotlin/com/huanshankeji/compose/material/TopAppBarScaffold.kt index 9918f66b..9129e4a2 100644 --- a/compose-multiplatform-material/src/commonMain/kotlin/com/huanshankeji/compose/material/TopAppBarScaffold.kt +++ b/compose-multiplatform-material/src/commonMain/kotlin/com/huanshankeji/compose/material/TopAppBarScaffold.kt @@ -8,7 +8,7 @@ expect class NavigationIconScope { fun NavButton(onClick: () -> Unit, content: @Composable () -> Unit) @Composable - fun MaterialIconNavButton(onClick: () -> Unit, materialIcon: MaterialIcon) + fun MaterialIconNavButton(onClick: () -> Unit, materialIcon: MaterialIcon, contentDescription: String?) } expect class TopAppBarActionsScope { @@ -16,7 +16,7 @@ expect class TopAppBarActionsScope { fun ActionButton(onClick: () -> Unit, content: @Composable () -> Unit) @Composable - fun MaterialIconActionButton(onClick: () -> Unit, materialIcon: MaterialIcon) + fun MaterialIconActionButton(onClick: () -> Unit, materialIcon: MaterialIcon, contentDescription: String?) } @Composable diff --git a/compose-multiplatform-material/src/jsMain/kotlin/com/huanshankeji/compose/material/Icon.kt b/compose-multiplatform-material/src/jsMain/kotlin/com/huanshankeji/compose/material/Icon.kt index 29e344f0..fe962278 100644 --- a/compose-multiplatform-material/src/jsMain/kotlin/com/huanshankeji/compose/material/Icon.kt +++ b/compose-multiplatform-material/src/jsMain/kotlin/com/huanshankeji/compose/material/Icon.kt @@ -4,7 +4,10 @@ import androidx.compose.runtime.Composable import com.huanshankeji.compose.material.icon.MaterialIcon import com.huanshankeji.compose.ui.ModifierOrAttrs import com.huanshankeji.compose.ui.toAttrs +import com.huanshankeji.compose.web.attributes.attrs +import com.huanshankeji.compose.web.attributes.plus import dev.petuska.kmdcx.icons.MDCIconSpan +import org.jetbrains.compose.web.attributes.AttrsScope import org.w3c.dom.HTMLSpanElement actual typealias IconElement = HTMLSpanElement @@ -13,5 +16,18 @@ actual typealias IconElement = HTMLSpanElement * There is often a better alternative of adding the CSS rule to the parent element to using this composable directly. */ @Composable -actual fun Icon(materialIcon: MaterialIcon, modifierOrAttrs: ModifierOrAttrs) = - MDCIconSpan(materialIcon.mdcIcon, attrs = modifierOrAttrs.toAttrs()) +actual fun Icon( + materialIcon: MaterialIcon, contentDescription: String?, modifierOrAttrs: ModifierOrAttrs +) = + MDCIconSpan(materialIcon.mdcIcon, attrs = attrs { + contentDescription(contentDescription) + } + modifierOrAttrs.toAttrs()) + +fun AttrsScope<*>.contentDescription(contentDescription: String?) = + contentDescription?.let { + // aria-label's semantics don't seem to meet the requirements perfectly because it labels an interactive element + // see: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label, https://stackoverflow.com/questions/22039910/what-is-aria-label-and-how-should-i-use-it + //attr("aria-label", it) + + title(it) + } diff --git a/compose-multiplatform-material/src/jsMain/kotlin/com/huanshankeji/compose/material/TopAppBarScaffold.kt b/compose-multiplatform-material/src/jsMain/kotlin/com/huanshankeji/compose/material/TopAppBarScaffold.kt index 90110ed8..5892b844 100644 --- a/compose-multiplatform-material/src/jsMain/kotlin/com/huanshankeji/compose/material/TopAppBarScaffold.kt +++ b/compose-multiplatform-material/src/jsMain/kotlin/com/huanshankeji/compose/material/TopAppBarScaffold.kt @@ -4,6 +4,7 @@ import androidx.compose.runtime.Composable import com.huanshankeji.compose.material.icon.MaterialIcon import dev.petuska.kmdc.top.app.bar.* import dev.petuska.kmdcx.icons.mdcIcon +import org.jetbrains.compose.web.dom.Text actual class NavigationIconScope(val mdcTopAppBarSectionScope: MDCTopAppBarSectionScope) { @Composable @@ -11,8 +12,11 @@ actual class NavigationIconScope(val mdcTopAppBarSectionScope: MDCTopAppBarSecti mdcTopAppBarSectionScope.NavButton(attrs = { onClick { onClick() } }) { content() } @Composable - actual fun MaterialIconNavButton(onClick: () -> Unit, materialIcon: MaterialIcon) = - mdcTopAppBarSectionScope.NavButton(attrs = { mdcIcon() }) { org.jetbrains.compose.web.dom.Text(materialIcon.mdcIcon.type) } + actual fun MaterialIconNavButton(onClick: () -> Unit, materialIcon: MaterialIcon, contentDescription: String?) = + mdcTopAppBarSectionScope.NavButton(attrs = { + mdcIcon() + contentDescription(contentDescription) + }) { Text(materialIcon.mdcIcon.type) } } actual class TopAppBarActionsScope(val mdcTopAppBarSectionScope: MDCTopAppBarSectionScope) { @@ -21,11 +25,11 @@ actual class TopAppBarActionsScope(val mdcTopAppBarSectionScope: MDCTopAppBarSec mdcTopAppBarSectionScope.ActionButton(attrs = { onClick { onClick() } }) { content() } @Composable - actual fun MaterialIconActionButton( - onClick: () -> Unit, - materialIcon: MaterialIcon - ) = - mdcTopAppBarSectionScope.ActionButton(attrs = { mdcIcon() }) { org.jetbrains.compose.web.dom.Text(materialIcon.mdcIcon.type) } + actual fun MaterialIconActionButton(onClick: () -> Unit, materialIcon: MaterialIcon, contentDescription: String?) = + mdcTopAppBarSectionScope.ActionButton(attrs = { + mdcIcon() + contentDescription(contentDescription) + }) { Text(materialIcon.mdcIcon.type) } } @Composable diff --git a/compose-multiplatform-material/src/jvmMain/kotlin/com/huanshankeji/compose/material/Icon.kt b/compose-multiplatform-material/src/jvmMain/kotlin/com/huanshankeji/compose/material/Icon.kt index 2a884765..4026c1f6 100644 --- a/compose-multiplatform-material/src/jvmMain/kotlin/com/huanshankeji/compose/material/Icon.kt +++ b/compose-multiplatform-material/src/jvmMain/kotlin/com/huanshankeji/compose/material/Icon.kt @@ -9,6 +9,7 @@ import com.huanshankeji.compose.ui.toModifier actual abstract class IconElement : Element() @Composable -actual fun Icon(materialIcon: MaterialIcon, modifierOrAttrs: ModifierOrAttrs) = - androidx.compose.material.Icon(materialIcon, null, modifierOrAttrs.toModifier()) -// no `contentDescription` for now +actual fun Icon( + materialIcon: MaterialIcon, contentDescription: String?, modifierOrAttrs: ModifierOrAttrs +) = + androidx.compose.material.Icon(materialIcon, contentDescription, modifierOrAttrs.toModifier()) diff --git a/compose-multiplatform-material/src/jvmMain/kotlin/com/huanshankeji/compose/material/TopAppBarScaffold.kt b/compose-multiplatform-material/src/jvmMain/kotlin/com/huanshankeji/compose/material/TopAppBarScaffold.kt index 00e3782e..2ade4454 100644 --- a/compose-multiplatform-material/src/jvmMain/kotlin/com/huanshankeji/compose/material/TopAppBarScaffold.kt +++ b/compose-multiplatform-material/src/jvmMain/kotlin/com/huanshankeji/compose/material/TopAppBarScaffold.kt @@ -12,8 +12,8 @@ actual class NavigationIconScope private constructor() { IconButton(onClick, content = content) @Composable - actual fun MaterialIconNavButton(onClick: () -> Unit, materialIcon: MaterialIcon) = - IconButton(onClick) { Icon(materialIcon) } + actual fun MaterialIconNavButton(onClick: () -> Unit, materialIcon: MaterialIcon, contentDescription: String?) = + IconButton(onClick) { Icon(materialIcon, contentDescription) } companion object { val instance = NavigationIconScope() @@ -26,8 +26,8 @@ actual class TopAppBarActionsScope(val rowScope: RowScope) { IconButton(onClick, content = content) @Composable - actual fun MaterialIconActionButton(onClick: () -> Unit, materialIcon: MaterialIcon) = - IconButton(onClick) { Icon(materialIcon) } + actual fun MaterialIconActionButton(onClick: () -> Unit, materialIcon: MaterialIcon, contentDescription: String?) = + IconButton(onClick) { Icon(materialIcon, contentDescription) } } From 73720f3d8dc748ea493b0cfdb02671a8f48cdf80 Mon Sep 17 00:00:00 2001 From: Shreck Ye Date: Sun, 11 Dec 2022 17:12:40 +0800 Subject: [PATCH 07/34] Remove the `compileOnly` dependencies for element links as they cause `compileKotlinJs` to fail `./gradlew build --rerun-tasks` has to be run to make the project build again. --- compose-multiplatform-common/build.gradle.kts | 2 +- compose-multiplatform-material/build.gradle.kts | 2 +- .../com/huanshankeji/compose/material/ListAndLazyColumn.kt | 2 +- gradle.properties | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/compose-multiplatform-common/build.gradle.kts b/compose-multiplatform-common/build.gradle.kts index bb4168d0..25e722b7 100644 --- a/compose-multiplatform-common/build.gradle.kts +++ b/compose-multiplatform-common/build.gradle.kts @@ -7,7 +7,7 @@ kotlin { named("commonMain") { dependencies { implementation(compose.runtime) - compileOnly(compose.foundation) // for KDoc element links only + //compileOnly(compose.foundation) // for KDoc element links only } } named("jvmMain") { diff --git a/compose-multiplatform-material/build.gradle.kts b/compose-multiplatform-material/build.gradle.kts index fd7bae21..dee2923d 100644 --- a/compose-multiplatform-material/build.gradle.kts +++ b/compose-multiplatform-material/build.gradle.kts @@ -8,7 +8,7 @@ kotlin { dependencies { implementation(compose.runtime) api(project(":compose-multiplatform-common")) - compileOnly(compose.material) // for KDoc element links only + //compileOnly(compose.material) // for KDoc element links only } } // TODO: a `jvmCommon` source set to share code for `jvm`/`desktop` and `android` diff --git a/compose-multiplatform-material/src/commonMain/kotlin/com/huanshankeji/compose/material/ListAndLazyColumn.kt b/compose-multiplatform-material/src/commonMain/kotlin/com/huanshankeji/compose/material/ListAndLazyColumn.kt index 31e8d3bd..f9ea3985 100644 --- a/compose-multiplatform-material/src/commonMain/kotlin/com/huanshankeji/compose/material/ListAndLazyColumn.kt +++ b/compose-multiplatform-material/src/commonMain/kotlin/com/huanshankeji/compose/material/ListAndLazyColumn.kt @@ -1,6 +1,6 @@ package com.huanshankeji.compose.material -import androidx.compose.foundation.lazy.LazyListScope +//import androidx.compose.foundation.lazy.LazyListScope import androidx.compose.runtime.Composable import com.huanshankeji.compose.ui.Element import com.huanshankeji.compose.ui.ModifierOrAttrs diff --git a/gradle.properties b/gradle.properties index cae61f9b..0df3dd3e 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,2 +1,2 @@ # for KDoc element links only -org.jetbrains.compose.experimental.jscanvas.enabled=true +#org.jetbrains.compose.experimental.jscanvas.enabled=true From 49c3176f8fcbab31819137321ab3ca2991260be2 Mon Sep 17 00:00:00 2001 From: Shreck Ye Date: Sun, 11 Dec 2022 17:27:25 +0800 Subject: [PATCH 08/34] Add a `List` demo that doesn't run on either desktop or web --- .../compose/material/demo/Composables.kt | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/demo/src/commonMain/kotlin/com/huanshankeji/compose/material/demo/Composables.kt b/demo/src/commonMain/kotlin/com/huanshankeji/compose/material/demo/Composables.kt index 70005f9b..9993b60b 100644 --- a/demo/src/commonMain/kotlin/com/huanshankeji/compose/material/demo/Composables.kt +++ b/demo/src/commonMain/kotlin/com/huanshankeji/compose/material/demo/Composables.kt @@ -32,6 +32,25 @@ fun App() { } IconButton(onClick, materialIcon = MaterialIcons.Search) + + List { + item { + Text("Ungrouped item") + } + items(count) { + Text("Ungrouped item $it/$count") + } + group(headerContent = { + Text("Group title") + }) { + item { + Text("Grouped item") + } + items(count) { + Text("Grouped item $it/$count") + } + } + } } } } From d39f6ece9023e333dca3951f78d077bfc03570c6 Mon Sep 17 00:00:00 2001 From: Shreck Ye Date: Sun, 11 Dec 2022 18:35:07 +0800 Subject: [PATCH 09/34] Debug why the demo fails to run and add a workaround for it On JVM it's found caused by a compiler bug of calling `item`/`items`/`group`(now renamed with the "Internal" suffix) in `ListScope` with default arguments. The JVM error message: > Task :demo:run Gtk-Message: 18:27:31.940: Failed to load module "canberra-gtk-module" Exception in thread "main" java.lang.NoSuchMethodError: 'void com.huanshankeji.compose.material.ListScope.item$default(com.huanshankeji.compose.material.ListScope, java.lang.Object, java.lang.Object, kotlin.jvm.functions.Function3, int, java.lang.Object)' The issue that `jsBrowserRun` fails to build seems to be caused by the same reason and is resolved too. Its original error message: > Task :demo:compileDevelopmentExecutableKotlinJs FAILED e: java.lang.AssertionError: Assertion failed Now the demo works again on both platforms. --- .../compose/material/ListAndLazyColumn.kt | 42 ++++++++++++++----- .../compose/material/ListAndLazyColumn.kt | 6 +-- .../compose/material/ListAndLazyColumnJvm.kt | 6 +-- 3 files changed, 37 insertions(+), 17 deletions(-) diff --git a/compose-multiplatform-material/src/commonMain/kotlin/com/huanshankeji/compose/material/ListAndLazyColumn.kt b/compose-multiplatform-material/src/commonMain/kotlin/com/huanshankeji/compose/material/ListAndLazyColumn.kt index f9ea3985..067c9ac0 100644 --- a/compose-multiplatform-material/src/commonMain/kotlin/com/huanshankeji/compose/material/ListAndLazyColumn.kt +++ b/compose-multiplatform-material/src/commonMain/kotlin/com/huanshankeji/compose/material/ListAndLazyColumn.kt @@ -7,18 +7,24 @@ import com.huanshankeji.compose.ui.ModifierOrAttrs expect abstract class ListElement : Element + /** @see LazyListScope */ expect class ListScope { - fun item(key: Any? = null, contentType: Any? = null, content: @Composable ItemScope.() -> Unit) + /* + There is a compiler bug of calling the functions below with default arguments. + TODO: report this and put the issue link here + */ + + internal fun itemInternal(key: Any? = null, contentType: Any? = null, content: @Composable ItemScope.() -> Unit) - fun items( + internal fun itemsInternal( count: Int, key: ((index: Int) -> Any)? = null, contentType: (index: Int) -> Any? = { null }, itemContent: @Composable ItemScope.(index: Int) -> Unit ) - fun group( + internal fun groupInternal( key: Any? = null, contentType: Any? = null, headerContent: @Composable HeaderScope.() -> Unit, @@ -26,16 +32,30 @@ expect class ListScope { ) } + +fun ListScope.item(key: Any? = null, contentType: Any? = null, content: @Composable ItemScope.() -> Unit) = + itemInternal(key, contentType, content) + +fun ListScope.items( + count: Int, + key: ((index: Int) -> Any)? = null, + contentType: (index: Int) -> Any? = { null }, + itemContent: @Composable ItemScope.(index: Int) -> Unit +) = + itemsInternal(count, key, contentType, itemContent) + +fun ListScope.group( + key: Any? = null, + contentType: Any? = null, + headerContent: @Composable HeaderScope.() -> Unit, + content: ListScope.() -> Unit +) = + groupInternal(key, contentType, headerContent, content) + + expect class ItemScope expect class HeaderScope -@Composable -expect fun List(modifierOrAttrs: ModifierOrAttrs = null, content: ListScope.() -> Unit) -/** - * An alias for [List] that follows the name of [androidx.compose.foundation.lazy.LazyColumn]. - * The current implementation is not actually lazy on web. - */ @Composable -fun LazyColumn(modifierOrAttrs: ModifierOrAttrs = null, content: ListScope.() -> Unit) = - List(modifierOrAttrs, content) +expect fun List(modifierOrAttrs: ModifierOrAttrs = null, content: ListScope.() -> Unit) diff --git a/compose-multiplatform-material/src/jsMain/kotlin/com/huanshankeji/compose/material/ListAndLazyColumn.kt b/compose-multiplatform-material/src/jsMain/kotlin/com/huanshankeji/compose/material/ListAndLazyColumn.kt index ac91e0b5..c4806b40 100644 --- a/compose-multiplatform-material/src/jsMain/kotlin/com/huanshankeji/compose/material/ListAndLazyColumn.kt +++ b/compose-multiplatform-material/src/jsMain/kotlin/com/huanshankeji/compose/material/ListAndLazyColumn.kt @@ -39,11 +39,11 @@ actual class ListScope( } - actual fun item(key: Any?, contentType: Any?, content: @Composable ItemScope.() -> Unit) = addComposable { + actual fun itemInternal(key: Any?, contentType: Any?, content: @Composable ItemScope.() -> Unit) = addComposable { mdcListScope.ListItem { ItemScope(this).content() } } - actual fun items( + actual fun itemsInternal( count: Int, key: ((index: Int) -> Any)?, contentType: (index: Int) -> Any?, @@ -54,7 +54,7 @@ actual class ListScope( } } - actual fun group( + actual fun groupInternal( key: Any?, contentType: Any?, headerContent: @Composable HeaderScope.() -> Unit, diff --git a/compose-multiplatform-material/src/jvmMain/kotlin/com/huanshankeji/compose/material/ListAndLazyColumnJvm.kt b/compose-multiplatform-material/src/jvmMain/kotlin/com/huanshankeji/compose/material/ListAndLazyColumnJvm.kt index 4176b579..1dc103c5 100644 --- a/compose-multiplatform-material/src/jvmMain/kotlin/com/huanshankeji/compose/material/ListAndLazyColumnJvm.kt +++ b/compose-multiplatform-material/src/jvmMain/kotlin/com/huanshankeji/compose/material/ListAndLazyColumnJvm.kt @@ -11,10 +11,10 @@ import com.huanshankeji.compose.ui.toModifier actual abstract class ListElement : Element() actual class ListScope(val lazyListScope: LazyListScope) { - actual fun item(key: Any?, contentType: Any?, content: @Composable ItemScope.() -> Unit) = + actual fun itemInternal(key: Any?, contentType: Any?, content: @Composable ItemScope.() -> Unit) = lazyListScope.item(key, contentType) { ItemScope(this).content() } - actual fun items( + actual fun itemsInternal( count: Int, key: ((index: Int) -> Any)?, contentType: (index: Int) -> Any?, @@ -23,7 +23,7 @@ actual class ListScope(val lazyListScope: LazyListScope) { lazyListScope.items(count, key, contentType) { ItemScope(this).itemContent(it) } @OptIn(ExperimentalFoundationApi::class) - actual fun group( + actual fun groupInternal( key: Any?, contentType: Any?, headerContent: @Composable HeaderScope.() -> Unit, From 4e4f60d11e7c6d55e970c173f9d2578843dd45ca Mon Sep 17 00:00:00 2001 From: Shreck Ye Date: Mon, 12 Dec 2022 02:17:18 +0800 Subject: [PATCH 10/34] Rename 2 properties to better names --- .../com/huanshankeji/compose/material/ListAndLazyColumn.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compose-multiplatform-material/src/jsMain/kotlin/com/huanshankeji/compose/material/ListAndLazyColumn.kt b/compose-multiplatform-material/src/jsMain/kotlin/com/huanshankeji/compose/material/ListAndLazyColumn.kt index c4806b40..387bd8ab 100644 --- a/compose-multiplatform-material/src/jsMain/kotlin/com/huanshankeji/compose/material/ListAndLazyColumn.kt +++ b/compose-multiplatform-material/src/jsMain/kotlin/com/huanshankeji/compose/material/ListAndLazyColumn.kt @@ -71,8 +71,8 @@ actual class ListScope( } } -actual class ItemScope(val mdcListScope: MDCListItemScope) -actual class HeaderScope(val htmlHeadingElementScope: ElementScope) +actual class ItemScope(val mdcListItemScope: MDCListItemScope) +actual class HeaderScope(val elementScope: ElementScope) @Composable actual fun List(modifierOrAttrs: ModifierOrAttrs, content: ListScope.() -> Unit) = From e65d9b2bff3d32ec6a2ec04e5a0b16253c8144d0 Mon Sep 17 00:00:00 2001 From: Shreck Ye Date: Mon, 12 Dec 2022 03:03:43 +0800 Subject: [PATCH 11/34] Revert "Debug why the demo fails to run and add a workaround for it" This reverts commit d39f6ece9023e333dca3951f78d077bfc03570c6. This is a partial revert. `LazyColumn` was removed by mistake. --- .../huanshankeji/compose/material/ListAndLazyColumn.kt | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/compose-multiplatform-material/src/commonMain/kotlin/com/huanshankeji/compose/material/ListAndLazyColumn.kt b/compose-multiplatform-material/src/commonMain/kotlin/com/huanshankeji/compose/material/ListAndLazyColumn.kt index 067c9ac0..7323fa93 100644 --- a/compose-multiplatform-material/src/commonMain/kotlin/com/huanshankeji/compose/material/ListAndLazyColumn.kt +++ b/compose-multiplatform-material/src/commonMain/kotlin/com/huanshankeji/compose/material/ListAndLazyColumn.kt @@ -59,3 +59,11 @@ expect class HeaderScope @Composable expect fun List(modifierOrAttrs: ModifierOrAttrs = null, content: ListScope.() -> Unit) + +/** + * An alias for [List] that follows the name of [androidx.compose.foundation.lazy.LazyColumn]. + * The current implementation is not actually lazy on web. + */ +@Composable +fun LazyColumn(modifierOrAttrs: ModifierOrAttrs = null, content: ListScope.() -> Unit) = + List(modifierOrAttrs, content) From f2024f3c3cbae63f04df3858f47f246dacb71885 Mon Sep 17 00:00:00 2001 From: Shreck Ye Date: Mon, 12 Dec 2022 18:07:58 +0800 Subject: [PATCH 12/34] Complete the modifications of commit b863a683bae1b67d60ba304f9b2e7d2d82e16785 --- .../kotlin/com/huanshankeji/compose/material/IconButton.kt | 6 +++--- .../com/huanshankeji/compose/material/demo/Composables.kt | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/compose-multiplatform-material/src/commonMain/kotlin/com/huanshankeji/compose/material/IconButton.kt b/compose-multiplatform-material/src/commonMain/kotlin/com/huanshankeji/compose/material/IconButton.kt index 6395c2a4..8dbe5aa3 100644 --- a/compose-multiplatform-material/src/commonMain/kotlin/com/huanshankeji/compose/material/IconButton.kt +++ b/compose-multiplatform-material/src/commonMain/kotlin/com/huanshankeji/compose/material/IconButton.kt @@ -19,7 +19,7 @@ expect fun IconButton( fun IconButton( onClick: () -> Unit, modifierOrAttrs: ModifierOrAttrs = null, - materialIcon: MaterialIcon + materialIcon: MaterialIcon, + contentDescription: String? ) = - IconButton(onClick, modifierOrAttrs) { Icon(materialIcon) } - + IconButton(onClick, modifierOrAttrs) { Icon(materialIcon, contentDescription) } diff --git a/demo/src/commonMain/kotlin/com/huanshankeji/compose/material/demo/Composables.kt b/demo/src/commonMain/kotlin/com/huanshankeji/compose/material/demo/Composables.kt index 9993b60b..6d5b7194 100644 --- a/demo/src/commonMain/kotlin/com/huanshankeji/compose/material/demo/Composables.kt +++ b/demo/src/commonMain/kotlin/com/huanshankeji/compose/material/demo/Composables.kt @@ -12,9 +12,9 @@ fun App() { TopAppBarScaffold({ Text("Compose Multiplatform Material demo") }, { - MaterialIconNavButton({}, MaterialIcons.Menu) + MaterialIconNavButton({}, MaterialIcons.Menu, "menu") }, { - MaterialIconActionButton({}, MaterialIcons.Search) + MaterialIconActionButton({}, MaterialIcons.Search, "search") }) { Card { Box({ @@ -31,7 +31,7 @@ fun App() { Label(count.toString()) } - IconButton(onClick, materialIcon = MaterialIcons.Search) + IconButton(onClick, materialIcon = MaterialIcons.Search, contentDescription = "increment count") List { item { From 6c429d36151825b977b50fea9937b6434c93923d Mon Sep 17 00:00:00 2001 From: Shreck Ye Date: Mon, 12 Dec 2022 18:43:33 +0800 Subject: [PATCH 13/34] Add `AttrBuilderContext?.toModifierOrAttrs()` and `Modifier.toModifierOrAttrs()` --- .../com/huanshankeji/compose/ui/ModifierOrAttrsScope.kt | 2 ++ .../com/huanshankeji/compose/ui/ModifierOrAttrsScope.kt | 3 +++ .../com/huanshankeji/compose/ui/ModifierOrAttrsScopeJvm.kt | 5 +++++ 3 files changed, 10 insertions(+) diff --git a/compose-multiplatform-common/src/commonMain/kotlin/com/huanshankeji/compose/ui/ModifierOrAttrsScope.kt b/compose-multiplatform-common/src/commonMain/kotlin/com/huanshankeji/compose/ui/ModifierOrAttrsScope.kt index 4c5117b3..3c520cb5 100644 --- a/compose-multiplatform-common/src/commonMain/kotlin/com/huanshankeji/compose/ui/ModifierOrAttrsScope.kt +++ b/compose-multiplatform-common/src/commonMain/kotlin/com/huanshankeji/compose/ui/ModifierOrAttrsScope.kt @@ -6,6 +6,8 @@ import com.huanshankeji.compose.ui.unit.SizeValue typealias ModifierOrAttrs = (ModifierOrAttrsScope.() -> Unit)? expect abstract class Element + +// TODO: add `out` to `TElement` expect class ModifierOrAttrsScope { fun style(builder: StyleScope.() -> Unit) } diff --git a/compose-multiplatform-common/src/jsMain/kotlin/com/huanshankeji/compose/ui/ModifierOrAttrsScope.kt b/compose-multiplatform-common/src/jsMain/kotlin/com/huanshankeji/compose/ui/ModifierOrAttrsScope.kt index a3cd403d..16d6ea10 100644 --- a/compose-multiplatform-common/src/jsMain/kotlin/com/huanshankeji/compose/ui/ModifierOrAttrsScope.kt +++ b/compose-multiplatform-common/src/jsMain/kotlin/com/huanshankeji/compose/ui/ModifierOrAttrsScope.kt @@ -9,6 +9,9 @@ import org.w3c.dom.HTMLElement fun ModifierOrAttrs.toAttrs(): AttrBuilderContext? = this?.let { { ModifierOrAttrsScope(this).it() } } +fun AttrBuilderContext?.toModifierOrAttrs(): ModifierOrAttrs = + this?.let { { attrsScope.it() } } + actual typealias Element = HTMLElement actual class ModifierOrAttrsScope(val attrsScope: AttrsScope) { diff --git a/compose-multiplatform-common/src/jvmMain/kotlin/com/huanshankeji/compose/ui/ModifierOrAttrsScopeJvm.kt b/compose-multiplatform-common/src/jvmMain/kotlin/com/huanshankeji/compose/ui/ModifierOrAttrsScopeJvm.kt index 66fdf361..ae80e6fd 100644 --- a/compose-multiplatform-common/src/jvmMain/kotlin/com/huanshankeji/compose/ui/ModifierOrAttrsScopeJvm.kt +++ b/compose-multiplatform-common/src/jvmMain/kotlin/com/huanshankeji/compose/ui/ModifierOrAttrsScopeJvm.kt @@ -9,6 +9,11 @@ fun ModifierOrAttrs.toModifier(): Modifier = ModifierOrAttrsScope(Modifier).apply(it).modifier } ?: Modifier +fun Modifier.toModifierOrAttrs(): ModifierOrAttrs = + if (this !== Modifier) { + { modify { this then this@toModifierOrAttrs } } + } else null + actual abstract class Element actual class ModifierOrAttrsScope(modifier: Modifier) { From 44bee3a6e18d5950d6b20c390d76451af6ec1f5d Mon Sep 17 00:00:00 2001 From: Shreck Ye Date: Mon, 12 Dec 2022 21:51:14 +0800 Subject: [PATCH 14/34] Add `out` to `TElement` --- .../kotlin/com/huanshankeji/compose/ui/ModifierOrAttrsScope.kt | 3 +-- .../kotlin/com/huanshankeji/compose/ui/ModifierOrAttrsScope.kt | 2 +- .../com/huanshankeji/compose/ui/ModifierOrAttrsScopeJvm.kt | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/compose-multiplatform-common/src/commonMain/kotlin/com/huanshankeji/compose/ui/ModifierOrAttrsScope.kt b/compose-multiplatform-common/src/commonMain/kotlin/com/huanshankeji/compose/ui/ModifierOrAttrsScope.kt index 3c520cb5..d92eb764 100644 --- a/compose-multiplatform-common/src/commonMain/kotlin/com/huanshankeji/compose/ui/ModifierOrAttrsScope.kt +++ b/compose-multiplatform-common/src/commonMain/kotlin/com/huanshankeji/compose/ui/ModifierOrAttrsScope.kt @@ -7,8 +7,7 @@ typealias ModifierOrAttrs = (ModifierOrAttrsScope.() -> Unit expect abstract class Element -// TODO: add `out` to `TElement` -expect class ModifierOrAttrsScope { +expect class ModifierOrAttrsScope { fun style(builder: StyleScope.() -> Unit) } diff --git a/compose-multiplatform-common/src/jsMain/kotlin/com/huanshankeji/compose/ui/ModifierOrAttrsScope.kt b/compose-multiplatform-common/src/jsMain/kotlin/com/huanshankeji/compose/ui/ModifierOrAttrsScope.kt index 16d6ea10..a8aea535 100644 --- a/compose-multiplatform-common/src/jsMain/kotlin/com/huanshankeji/compose/ui/ModifierOrAttrsScope.kt +++ b/compose-multiplatform-common/src/jsMain/kotlin/com/huanshankeji/compose/ui/ModifierOrAttrsScope.kt @@ -14,7 +14,7 @@ fun AttrBuilderContext?.toModifierOrAttrs(): Modi actual typealias Element = HTMLElement -actual class ModifierOrAttrsScope(val attrsScope: AttrsScope) { +actual class ModifierOrAttrsScope(val attrsScope: AttrsScope) { actual fun style(builder: StyleScope.() -> Unit) = attrsScope.style { StyleScope(this).builder() } } diff --git a/compose-multiplatform-common/src/jvmMain/kotlin/com/huanshankeji/compose/ui/ModifierOrAttrsScopeJvm.kt b/compose-multiplatform-common/src/jvmMain/kotlin/com/huanshankeji/compose/ui/ModifierOrAttrsScopeJvm.kt index ae80e6fd..b5967d0e 100644 --- a/compose-multiplatform-common/src/jvmMain/kotlin/com/huanshankeji/compose/ui/ModifierOrAttrsScopeJvm.kt +++ b/compose-multiplatform-common/src/jvmMain/kotlin/com/huanshankeji/compose/ui/ModifierOrAttrsScopeJvm.kt @@ -16,7 +16,7 @@ fun Modifier.toModifierOrAttrs(): ModifierOrAttrs actual abstract class Element -actual class ModifierOrAttrsScope(modifier: Modifier) { +actual class ModifierOrAttrsScope(modifier: Modifier) { var modifier: Modifier = modifier private set From d93663fcbf21fda4c847f73415f2fa24dd1edda8 Mon Sep 17 00:00:00 2001 From: Shreck Ye Date: Tue, 13 Dec 2022 00:37:53 +0800 Subject: [PATCH 15/34] Add `Column` and `Row` and update `:demo` --- .../compose/layout/{Layouts.kt => Box.kt} | 0 .../com/huanshankeji/compose/layout/Column.kt | 11 ++++ .../com/huanshankeji/compose/layout/Row.kt | 11 ++++ .../compose/layout/{Layouts.kt => Box.kt} | 0 .../com/huanshankeji/compose/layout/Column.kt | 21 ++++++++ .../com/huanshankeji/compose/layout/Row.kt | 21 ++++++++ .../compose/layout/{Layouts.kt => Box.kt} | 0 .../com/huanshankeji/compose/layout/Column.kt | 14 +++++ .../com/huanshankeji/compose/layout/Row.kt | 13 +++++ .../compose/material/demo/Composables.kt | 52 +++++++++++-------- 10 files changed, 122 insertions(+), 21 deletions(-) rename compose-multiplatform-common/src/commonMain/kotlin/com/huanshankeji/compose/layout/{Layouts.kt => Box.kt} (100%) create mode 100644 compose-multiplatform-common/src/commonMain/kotlin/com/huanshankeji/compose/layout/Column.kt create mode 100644 compose-multiplatform-common/src/commonMain/kotlin/com/huanshankeji/compose/layout/Row.kt rename compose-multiplatform-common/src/jsMain/kotlin/com/huanshankeji/compose/layout/{Layouts.kt => Box.kt} (100%) create mode 100644 compose-multiplatform-common/src/jsMain/kotlin/com/huanshankeji/compose/layout/Column.kt create mode 100644 compose-multiplatform-common/src/jsMain/kotlin/com/huanshankeji/compose/layout/Row.kt rename compose-multiplatform-common/src/jvmMain/kotlin/com/huanshankeji/compose/layout/{Layouts.kt => Box.kt} (100%) create mode 100644 compose-multiplatform-common/src/jvmMain/kotlin/com/huanshankeji/compose/layout/Column.kt create mode 100644 compose-multiplatform-common/src/jvmMain/kotlin/com/huanshankeji/compose/layout/Row.kt diff --git a/compose-multiplatform-common/src/commonMain/kotlin/com/huanshankeji/compose/layout/Layouts.kt b/compose-multiplatform-common/src/commonMain/kotlin/com/huanshankeji/compose/layout/Box.kt similarity index 100% rename from compose-multiplatform-common/src/commonMain/kotlin/com/huanshankeji/compose/layout/Layouts.kt rename to compose-multiplatform-common/src/commonMain/kotlin/com/huanshankeji/compose/layout/Box.kt diff --git a/compose-multiplatform-common/src/commonMain/kotlin/com/huanshankeji/compose/layout/Column.kt b/compose-multiplatform-common/src/commonMain/kotlin/com/huanshankeji/compose/layout/Column.kt new file mode 100644 index 00000000..544940d0 --- /dev/null +++ b/compose-multiplatform-common/src/commonMain/kotlin/com/huanshankeji/compose/layout/Column.kt @@ -0,0 +1,11 @@ +package com.huanshankeji.compose.layout + +import androidx.compose.runtime.Composable +import com.huanshankeji.compose.ui.Element +import com.huanshankeji.compose.ui.ModifierOrAttrs + +expect abstract class ColumnElement : Element +expect interface ColumnScope + +@Composable +expect fun Column(modifierOrAttrs: ModifierOrAttrs = null, content: @Composable ColumnScope.() -> Unit) diff --git a/compose-multiplatform-common/src/commonMain/kotlin/com/huanshankeji/compose/layout/Row.kt b/compose-multiplatform-common/src/commonMain/kotlin/com/huanshankeji/compose/layout/Row.kt new file mode 100644 index 00000000..2b086fec --- /dev/null +++ b/compose-multiplatform-common/src/commonMain/kotlin/com/huanshankeji/compose/layout/Row.kt @@ -0,0 +1,11 @@ +package com.huanshankeji.compose.layout + +import androidx.compose.runtime.Composable +import com.huanshankeji.compose.ui.Element +import com.huanshankeji.compose.ui.ModifierOrAttrs + +expect abstract class RowElement : Element +expect interface RowScope + +@Composable +expect fun Row(modifierOrAttrs: ModifierOrAttrs = null, content: @Composable RowScope.() -> Unit) diff --git a/compose-multiplatform-common/src/jsMain/kotlin/com/huanshankeji/compose/layout/Layouts.kt b/compose-multiplatform-common/src/jsMain/kotlin/com/huanshankeji/compose/layout/Box.kt similarity index 100% rename from compose-multiplatform-common/src/jsMain/kotlin/com/huanshankeji/compose/layout/Layouts.kt rename to compose-multiplatform-common/src/jsMain/kotlin/com/huanshankeji/compose/layout/Box.kt diff --git a/compose-multiplatform-common/src/jsMain/kotlin/com/huanshankeji/compose/layout/Column.kt b/compose-multiplatform-common/src/jsMain/kotlin/com/huanshankeji/compose/layout/Column.kt new file mode 100644 index 00000000..29ac531d --- /dev/null +++ b/compose-multiplatform-common/src/jsMain/kotlin/com/huanshankeji/compose/layout/Column.kt @@ -0,0 +1,21 @@ +package com.huanshankeji.compose.layout + +import androidx.compose.runtime.Composable +import com.huanshankeji.compose.ui.ModifierOrAttrs +import org.jetbrains.compose.web.dom.ElementScope +import org.w3c.dom.HTMLDivElement + +actual typealias ColumnElement = HTMLDivElement + +actual interface ColumnScope { + val elementScope: ElementScope + + class Impl(override val elementScope: ElementScope) : ColumnScope +} + +@Composable +actual fun Column(modifierOrAttrs: ModifierOrAttrs, content: @Composable ColumnScope.() -> Unit) = + // TODO: `modifierOrAttrs` not used yet + com.huanshankeji.compose.web.Column { + ColumnScope.Impl(this).content() + } diff --git a/compose-multiplatform-common/src/jsMain/kotlin/com/huanshankeji/compose/layout/Row.kt b/compose-multiplatform-common/src/jsMain/kotlin/com/huanshankeji/compose/layout/Row.kt new file mode 100644 index 00000000..4dc97e1f --- /dev/null +++ b/compose-multiplatform-common/src/jsMain/kotlin/com/huanshankeji/compose/layout/Row.kt @@ -0,0 +1,21 @@ +package com.huanshankeji.compose.layout + +import androidx.compose.runtime.Composable +import com.huanshankeji.compose.ui.ModifierOrAttrs +import org.jetbrains.compose.web.dom.ElementScope +import org.w3c.dom.HTMLDivElement + +actual typealias RowElement = HTMLDivElement + +actual interface RowScope { + val elementScope: ElementScope + + class Impl(override val elementScope: ElementScope) : RowScope +} + +@Composable +actual fun Row(modifierOrAttrs: ModifierOrAttrs, content: @Composable RowScope.() -> Unit) = + // TODO: `modifierOrAttrs` not used yet + com.huanshankeji.compose.web.Row { + RowScope.Impl(this).content() + } diff --git a/compose-multiplatform-common/src/jvmMain/kotlin/com/huanshankeji/compose/layout/Layouts.kt b/compose-multiplatform-common/src/jvmMain/kotlin/com/huanshankeji/compose/layout/Box.kt similarity index 100% rename from compose-multiplatform-common/src/jvmMain/kotlin/com/huanshankeji/compose/layout/Layouts.kt rename to compose-multiplatform-common/src/jvmMain/kotlin/com/huanshankeji/compose/layout/Box.kt diff --git a/compose-multiplatform-common/src/jvmMain/kotlin/com/huanshankeji/compose/layout/Column.kt b/compose-multiplatform-common/src/jvmMain/kotlin/com/huanshankeji/compose/layout/Column.kt new file mode 100644 index 00000000..1efe65e5 --- /dev/null +++ b/compose-multiplatform-common/src/jvmMain/kotlin/com/huanshankeji/compose/layout/Column.kt @@ -0,0 +1,14 @@ +package com.huanshankeji.compose.layout + +import androidx.compose.runtime.Composable +import com.huanshankeji.compose.ui.Element +import com.huanshankeji.compose.ui.ModifierOrAttrs +import com.huanshankeji.compose.ui.toModifier + + +actual abstract class ColumnElement : Element() +actual typealias ColumnScope = androidx.compose.foundation.layout.ColumnScope + +@Composable +actual fun Column(modifierOrAttrs: ModifierOrAttrs, content: @Composable ColumnScope.() -> Unit) = + androidx.compose.foundation.layout.Column(modifierOrAttrs.toModifier(), content = content) diff --git a/compose-multiplatform-common/src/jvmMain/kotlin/com/huanshankeji/compose/layout/Row.kt b/compose-multiplatform-common/src/jvmMain/kotlin/com/huanshankeji/compose/layout/Row.kt new file mode 100644 index 00000000..09ae0722 --- /dev/null +++ b/compose-multiplatform-common/src/jvmMain/kotlin/com/huanshankeji/compose/layout/Row.kt @@ -0,0 +1,13 @@ +package com.huanshankeji.compose.layout + +import androidx.compose.runtime.Composable +import com.huanshankeji.compose.ui.Element +import com.huanshankeji.compose.ui.ModifierOrAttrs +import com.huanshankeji.compose.ui.toModifier + +actual abstract class RowElement : Element() +actual typealias RowScope = androidx.compose.foundation.layout.RowScope + +@Composable +actual fun Row(modifierOrAttrs: ModifierOrAttrs, content: @Composable RowScope.() -> Unit) = + androidx.compose.foundation.layout.Row(modifierOrAttrs.toModifier(), content = content) diff --git a/demo/src/commonMain/kotlin/com/huanshankeji/compose/material/demo/Composables.kt b/demo/src/commonMain/kotlin/com/huanshankeji/compose/material/demo/Composables.kt index 6d5b7194..6b77e203 100644 --- a/demo/src/commonMain/kotlin/com/huanshankeji/compose/material/demo/Composables.kt +++ b/demo/src/commonMain/kotlin/com/huanshankeji/compose/material/demo/Composables.kt @@ -3,6 +3,8 @@ package com.huanshankeji.compose.material.demo import androidx.compose.runtime.* import com.huanshankeji.compose.BasicText import com.huanshankeji.compose.layout.Box +import com.huanshankeji.compose.layout.Column +import com.huanshankeji.compose.layout.Row import com.huanshankeji.compose.material.* import com.huanshankeji.compose.material.icon.MaterialIcons import com.huanshankeji.compose.ui.unit.dpOrPx @@ -16,38 +18,46 @@ fun App() { }, { MaterialIconActionButton({}, MaterialIcons.Search, "search") }) { - Card { - Box({ - style { - padding(16.dpOrPx) - } - }) { + Card({ + style { + padding(16.dpOrPx) + } + }) { + Column { BasicText("basic text") Text("Material text") var count by remember { mutableStateOf(0) } val onClick: () -> Unit = { count++ } - Button(onClick) { - Label(count.toString()) - } - - IconButton(onClick, materialIcon = MaterialIcons.Search, contentDescription = "increment count") - List { - item { - Text("Ungrouped item") + Row { + Button(onClick) { + Label(count.toString()) } - items(count) { - Text("Ungrouped item $it/$count") + IconButton(onClick, materialIcon = MaterialIcons.Search, contentDescription = "increment count") + } + + Box({ + style { + padding(16.dpOrPx) } - group(headerContent = { - Text("Group title") - }) { + }) { + List { item { - Text("Grouped item") + Text("Ungrouped item") } items(count) { - Text("Grouped item $it/$count") + Text("Ungrouped item $it/$count") + } + group(headerContent = { + Text("Group title") + }) { + item { + Text("Grouped item") + } + items(count) { + Text("Grouped item $it/$count") + } } } } From 94d29a68b73f54c11ace38e143262280b37cfd81 Mon Sep 17 00:00:00 2001 From: Shreck Ye Date: Tue, 13 Dec 2022 17:47:52 +0800 Subject: [PATCH 16/34] Improve the `Text` APIs 1. add `RawText`; 1. add an opt-in requirement for `com.huanshankeji.compose.material.Text`; 1. add `modifierAndAttrs` arguments. --- .../com/huanshankeji/compose/BasicText.kt | 6 ++++- .../com/huanshankeji/compose/RawText.kt | 7 ++++++ .../com/huanshankeji/compose/BasicText.kt | 10 ++++++-- .../com/huanshankeji/compose/RawText.kt | 8 ++++++ .../com/huanshankeji/compose/BasicText.kt | 9 +++++-- .../com/huanshankeji/compose/RawText.kt | 7 ++++++ .../com/huanshankeji/compose/material/Text.kt | 25 ++++++++++++++++++- .../com/huanshankeji/compose/material/Text.kt | 8 ++++-- .../com/huanshankeji/compose/material/Text.kt | 7 ------ .../huanshankeji/compose/material/TextJvm.kt | 12 +++++++++ .../compose/material/demo/Composables.kt | 1 + 11 files changed, 85 insertions(+), 15 deletions(-) create mode 100644 compose-multiplatform-common/src/commonMain/kotlin/com/huanshankeji/compose/RawText.kt create mode 100644 compose-multiplatform-common/src/jsMain/kotlin/com/huanshankeji/compose/RawText.kt create mode 100644 compose-multiplatform-common/src/jvmMain/kotlin/com/huanshankeji/compose/RawText.kt delete mode 100644 compose-multiplatform-material/src/jvmMain/kotlin/com/huanshankeji/compose/material/Text.kt create mode 100644 compose-multiplatform-material/src/jvmMain/kotlin/com/huanshankeji/compose/material/TextJvm.kt diff --git a/compose-multiplatform-common/src/commonMain/kotlin/com/huanshankeji/compose/BasicText.kt b/compose-multiplatform-common/src/commonMain/kotlin/com/huanshankeji/compose/BasicText.kt index 91286432..0dda24b9 100644 --- a/compose-multiplatform-common/src/commonMain/kotlin/com/huanshankeji/compose/BasicText.kt +++ b/compose-multiplatform-common/src/commonMain/kotlin/com/huanshankeji/compose/BasicText.kt @@ -1,6 +1,10 @@ package com.huanshankeji.compose import androidx.compose.runtime.Composable +import com.huanshankeji.compose.ui.Element +import com.huanshankeji.compose.ui.ModifierOrAttrs + +expect abstract class BasicTextElement : Element @Composable -expect fun BasicText(text: String) +expect fun BasicText(text: String, modifierOrAttrs: ModifierOrAttrs = null) diff --git a/compose-multiplatform-common/src/commonMain/kotlin/com/huanshankeji/compose/RawText.kt b/compose-multiplatform-common/src/commonMain/kotlin/com/huanshankeji/compose/RawText.kt new file mode 100644 index 00000000..333c75f3 --- /dev/null +++ b/compose-multiplatform-common/src/commonMain/kotlin/com/huanshankeji/compose/RawText.kt @@ -0,0 +1,7 @@ +package com.huanshankeji.compose + +import androidx.compose.runtime.Composable + +/** A raw text composable which doesn't add any element on web. */ +@Composable +expect fun RawText(text: String) diff --git a/compose-multiplatform-common/src/jsMain/kotlin/com/huanshankeji/compose/BasicText.kt b/compose-multiplatform-common/src/jsMain/kotlin/com/huanshankeji/compose/BasicText.kt index 2b388aac..ea284ef7 100644 --- a/compose-multiplatform-common/src/jsMain/kotlin/com/huanshankeji/compose/BasicText.kt +++ b/compose-multiplatform-common/src/jsMain/kotlin/com/huanshankeji/compose/BasicText.kt @@ -1,8 +1,14 @@ package com.huanshankeji.compose import androidx.compose.runtime.Composable +import com.huanshankeji.compose.ui.ModifierOrAttrs +import com.huanshankeji.compose.ui.toAttrs +import org.jetbrains.compose.web.dom.Span import org.jetbrains.compose.web.dom.Text +import org.w3c.dom.HTMLSpanElement + +actual typealias BasicTextElement = HTMLSpanElement @Composable -actual fun BasicText(text: String) = - Text(text) +actual fun BasicText(text: String, modifierOrAttrs: ModifierOrAttrs) = + Span(modifierOrAttrs.toAttrs()) { Text(text) } diff --git a/compose-multiplatform-common/src/jsMain/kotlin/com/huanshankeji/compose/RawText.kt b/compose-multiplatform-common/src/jsMain/kotlin/com/huanshankeji/compose/RawText.kt new file mode 100644 index 00000000..b22cfe23 --- /dev/null +++ b/compose-multiplatform-common/src/jsMain/kotlin/com/huanshankeji/compose/RawText.kt @@ -0,0 +1,8 @@ +package com.huanshankeji.compose + +import androidx.compose.runtime.Composable +import org.jetbrains.compose.web.dom.Text + +@Composable +actual fun RawText(text: String) = + Text(text) \ No newline at end of file diff --git a/compose-multiplatform-common/src/jvmMain/kotlin/com/huanshankeji/compose/BasicText.kt b/compose-multiplatform-common/src/jvmMain/kotlin/com/huanshankeji/compose/BasicText.kt index 55e1c938..8b30fc55 100644 --- a/compose-multiplatform-common/src/jvmMain/kotlin/com/huanshankeji/compose/BasicText.kt +++ b/compose-multiplatform-common/src/jvmMain/kotlin/com/huanshankeji/compose/BasicText.kt @@ -1,7 +1,12 @@ package com.huanshankeji.compose import androidx.compose.runtime.Composable +import com.huanshankeji.compose.ui.Element +import com.huanshankeji.compose.ui.ModifierOrAttrs +import com.huanshankeji.compose.ui.toModifier + +actual abstract class BasicTextElement : Element() @Composable -actual fun BasicText(text: String) = - androidx.compose.foundation.text.BasicText(text) +actual fun BasicText(text: String, modifierOrAttrs: ModifierOrAttrs) = + androidx.compose.foundation.text.BasicText(text, modifierOrAttrs.toModifier()) diff --git a/compose-multiplatform-common/src/jvmMain/kotlin/com/huanshankeji/compose/RawText.kt b/compose-multiplatform-common/src/jvmMain/kotlin/com/huanshankeji/compose/RawText.kt new file mode 100644 index 00000000..b5e2e949 --- /dev/null +++ b/compose-multiplatform-common/src/jvmMain/kotlin/com/huanshankeji/compose/RawText.kt @@ -0,0 +1,7 @@ +package com.huanshankeji.compose + +import androidx.compose.runtime.Composable + +@Composable +actual fun RawText(text: String) = + androidx.compose.foundation.text.BasicText(text) diff --git a/compose-multiplatform-material/src/commonMain/kotlin/com/huanshankeji/compose/material/Text.kt b/compose-multiplatform-material/src/commonMain/kotlin/com/huanshankeji/compose/material/Text.kt index c7849160..dad21600 100644 --- a/compose-multiplatform-material/src/commonMain/kotlin/com/huanshankeji/compose/material/Text.kt +++ b/compose-multiplatform-material/src/commonMain/kotlin/com/huanshankeji/compose/material/Text.kt @@ -1,6 +1,29 @@ package com.huanshankeji.compose.material import androidx.compose.runtime.Composable +import com.huanshankeji.compose.ui.Element +import com.huanshankeji.compose.ui.ModifierOrAttrs +expect abstract class TextElement : Element + +@RequiresOptIn( + "The `com.huanshankeji.compose.material.Text` function " + + "can be easily confused with other Composable functions named `Text` " + + "such as `androidx.compose.material.Text` and `org.jetbrains.compose.web.dom.Text` " + + "if not careful. " + + "Opt-in to use this API or use `MaterialText` instead.", + RequiresOptIn.Level.WARNING +) +@Retention(AnnotationRetention.BINARY) +@Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION) +annotation class ConfusableTextApi + +@ConfusableTextApi +@Composable +expect fun Text(text: String, modifierOrAttrs: ModifierOrAttrs = null) + +@Suppress("NOTHING_TO_INLINE") +@OptIn(ConfusableTextApi::class) @Composable -expect fun Text(text: String) +inline fun MaterialText(text: String, noinline modifierOrAttrs: ModifierOrAttrs = null) = + Text(text, modifierOrAttrs) diff --git a/compose-multiplatform-material/src/jsMain/kotlin/com/huanshankeji/compose/material/Text.kt b/compose-multiplatform-material/src/jsMain/kotlin/com/huanshankeji/compose/material/Text.kt index 2fd065c4..24dd538e 100644 --- a/compose-multiplatform-material/src/jsMain/kotlin/com/huanshankeji/compose/material/Text.kt +++ b/compose-multiplatform-material/src/jsMain/kotlin/com/huanshankeji/compose/material/Text.kt @@ -2,7 +2,11 @@ package com.huanshankeji.compose.material import androidx.compose.runtime.Composable import com.huanshankeji.compose.BasicText +import com.huanshankeji.compose.ui.ModifierOrAttrs +import org.w3c.dom.HTMLSpanElement + +actual typealias TextElement = HTMLSpanElement @Composable -actual fun Text(text: String) = - BasicText(text) +actual fun Text(text: String, modifierOrAttrs: ModifierOrAttrs) = + BasicText(text, modifierOrAttrs) diff --git a/compose-multiplatform-material/src/jvmMain/kotlin/com/huanshankeji/compose/material/Text.kt b/compose-multiplatform-material/src/jvmMain/kotlin/com/huanshankeji/compose/material/Text.kt deleted file mode 100644 index d2bc1cfc..00000000 --- a/compose-multiplatform-material/src/jvmMain/kotlin/com/huanshankeji/compose/material/Text.kt +++ /dev/null @@ -1,7 +0,0 @@ -package com.huanshankeji.compose.material - -import androidx.compose.runtime.Composable - -@Composable -actual fun Text(text: String) = - androidx.compose.material.Text(text) diff --git a/compose-multiplatform-material/src/jvmMain/kotlin/com/huanshankeji/compose/material/TextJvm.kt b/compose-multiplatform-material/src/jvmMain/kotlin/com/huanshankeji/compose/material/TextJvm.kt new file mode 100644 index 00000000..047af934 --- /dev/null +++ b/compose-multiplatform-material/src/jvmMain/kotlin/com/huanshankeji/compose/material/TextJvm.kt @@ -0,0 +1,12 @@ +package com.huanshankeji.compose.material + +import androidx.compose.runtime.Composable +import com.huanshankeji.compose.ui.Element +import com.huanshankeji.compose.ui.ModifierOrAttrs +import com.huanshankeji.compose.ui.toModifier + +actual abstract class TextElement : Element() + +@Composable +actual fun Text(text: String, modifierOrAttrs: ModifierOrAttrs) = + androidx.compose.material.Text(text, modifierOrAttrs.toModifier()) diff --git a/demo/src/commonMain/kotlin/com/huanshankeji/compose/material/demo/Composables.kt b/demo/src/commonMain/kotlin/com/huanshankeji/compose/material/demo/Composables.kt index 6b77e203..23667a09 100644 --- a/demo/src/commonMain/kotlin/com/huanshankeji/compose/material/demo/Composables.kt +++ b/demo/src/commonMain/kotlin/com/huanshankeji/compose/material/demo/Composables.kt @@ -9,6 +9,7 @@ import com.huanshankeji.compose.material.* import com.huanshankeji.compose.material.icon.MaterialIcons import com.huanshankeji.compose.ui.unit.dpOrPx +@OptIn(ConfusableTextApi::class) @Composable fun App() { TopAppBarScaffold({ From 1987b57cdef6fc4354726c6db3d8763496ea14fb Mon Sep 17 00:00:00 2001 From: Shreck Ye Date: Tue, 13 Dec 2022 17:54:09 +0800 Subject: [PATCH 17/34] Add `MaterialIcons.Add` for the demo --- .../com/huanshankeji/compose/material/icon/MaterialIcons.kt | 3 ++- .../com/huanshankeji/compose/material/icon/MaterialIcons.kt | 1 + .../com/huanshankeji/compose/material/icon/MaterialIcons.kt | 2 ++ .../com/huanshankeji/compose/material/demo/Composables.kt | 2 +- 4 files changed, 6 insertions(+), 2 deletions(-) diff --git a/compose-multiplatform-material/src/commonMain/kotlin/com/huanshankeji/compose/material/icon/MaterialIcons.kt b/compose-multiplatform-material/src/commonMain/kotlin/com/huanshankeji/compose/material/icon/MaterialIcons.kt index 35baf8bd..51c5df70 100644 --- a/compose-multiplatform-material/src/commonMain/kotlin/com/huanshankeji/compose/material/icon/MaterialIcons.kt +++ b/compose-multiplatform-material/src/commonMain/kotlin/com/huanshankeji/compose/material/icon/MaterialIcons.kt @@ -3,6 +3,7 @@ package com.huanshankeji.compose.material.icon expect class MaterialIcon expect object MaterialIcons { - val Menu : MaterialIcon + val Add: MaterialIcon + val Menu: MaterialIcon val Search : MaterialIcon } diff --git a/compose-multiplatform-material/src/jsMain/kotlin/com/huanshankeji/compose/material/icon/MaterialIcons.kt b/compose-multiplatform-material/src/jsMain/kotlin/com/huanshankeji/compose/material/icon/MaterialIcons.kt index bc0c10ef..7d6075a9 100644 --- a/compose-multiplatform-material/src/jsMain/kotlin/com/huanshankeji/compose/material/icon/MaterialIcons.kt +++ b/compose-multiplatform-material/src/jsMain/kotlin/com/huanshankeji/compose/material/icon/MaterialIcons.kt @@ -5,6 +5,7 @@ import dev.petuska.kmdcx.icons.MDCIcon actual class MaterialIcon(val mdcIcon: MDCIcon) actual object MaterialIcons { + actual val Add = MaterialIcon(MDCIcon.Add) actual val Menu = MaterialIcon(MDCIcon.Menu) actual val Search = MaterialIcon(MDCIcon.Search) } diff --git a/compose-multiplatform-material/src/jvmMain/kotlin/com/huanshankeji/compose/material/icon/MaterialIcons.kt b/compose-multiplatform-material/src/jvmMain/kotlin/com/huanshankeji/compose/material/icon/MaterialIcons.kt index caea816d..671dcb2a 100644 --- a/compose-multiplatform-material/src/jvmMain/kotlin/com/huanshankeji/compose/material/icon/MaterialIcons.kt +++ b/compose-multiplatform-material/src/jvmMain/kotlin/com/huanshankeji/compose/material/icon/MaterialIcons.kt @@ -1,6 +1,7 @@ package com.huanshankeji.compose.material.icon import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Add import androidx.compose.material.icons.filled.Menu import androidx.compose.material.icons.filled.Search import androidx.compose.ui.graphics.vector.ImageVector @@ -8,6 +9,7 @@ import androidx.compose.ui.graphics.vector.ImageVector actual typealias MaterialIcon = ImageVector actual object MaterialIcons { + actual val Add = Icons.Default.Add actual val Menu = Icons.Default.Menu actual val Search = Icons.Default.Search } diff --git a/demo/src/commonMain/kotlin/com/huanshankeji/compose/material/demo/Composables.kt b/demo/src/commonMain/kotlin/com/huanshankeji/compose/material/demo/Composables.kt index 23667a09..3d93e9a1 100644 --- a/demo/src/commonMain/kotlin/com/huanshankeji/compose/material/demo/Composables.kt +++ b/demo/src/commonMain/kotlin/com/huanshankeji/compose/material/demo/Composables.kt @@ -35,7 +35,7 @@ fun App() { Button(onClick) { Label(count.toString()) } - IconButton(onClick, materialIcon = MaterialIcons.Search, contentDescription = "increment count") + IconButton(onClick, materialIcon = MaterialIcons.Add, contentDescription = "increment count") } Box({ From 26f214b7d9d9c7a4435369a0dee9c226df77cfa2 Mon Sep 17 00:00:00 2001 From: Shreck Ye Date: Tue, 13 Dec 2022 18:30:49 +0800 Subject: [PATCH 18/34] Rename `StyleScope.padding` to `margin` and ensure its visual consistency on desktop and web --- .../com/huanshankeji/compose/ui/ModifierOrAttrsScope.kt | 2 +- .../com/huanshankeji/compose/ui/ModifierOrAttrsScope.kt | 6 +++--- .../com/huanshankeji/compose/ui/ModifierOrAttrsScopeJvm.kt | 2 +- .../com/huanshankeji/compose/material/demo/Composables.kt | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/compose-multiplatform-common/src/commonMain/kotlin/com/huanshankeji/compose/ui/ModifierOrAttrsScope.kt b/compose-multiplatform-common/src/commonMain/kotlin/com/huanshankeji/compose/ui/ModifierOrAttrsScope.kt index d92eb764..95ebe3f9 100644 --- a/compose-multiplatform-common/src/commonMain/kotlin/com/huanshankeji/compose/ui/ModifierOrAttrsScope.kt +++ b/compose-multiplatform-common/src/commonMain/kotlin/com/huanshankeji/compose/ui/ModifierOrAttrsScope.kt @@ -12,7 +12,7 @@ expect class ModifierOrAttrsScope { } expect class StyleScope { - fun padding(value: SizeValue) + fun margin(value: SizeValue) } /* diff --git a/compose-multiplatform-common/src/jsMain/kotlin/com/huanshankeji/compose/ui/ModifierOrAttrsScope.kt b/compose-multiplatform-common/src/jsMain/kotlin/com/huanshankeji/compose/ui/ModifierOrAttrsScope.kt index a8aea535..60cea914 100644 --- a/compose-multiplatform-common/src/jsMain/kotlin/com/huanshankeji/compose/ui/ModifierOrAttrsScope.kt +++ b/compose-multiplatform-common/src/jsMain/kotlin/com/huanshankeji/compose/ui/ModifierOrAttrsScope.kt @@ -2,7 +2,7 @@ package com.huanshankeji.compose.ui import com.huanshankeji.compose.ui.unit.SizeValue import org.jetbrains.compose.web.attributes.AttrsScope -import org.jetbrains.compose.web.css.padding +import org.jetbrains.compose.web.css.margin import org.jetbrains.compose.web.dom.AttrBuilderContext import org.w3c.dom.HTMLElement @@ -20,6 +20,6 @@ actual class ModifierOrAttrsScope(val attrsScope: AttrsS } actual class StyleScope(val styleScope: org.jetbrains.compose.web.css.StyleScope) { - actual fun padding(value: SizeValue) = - styleScope.padding(value.platformValue) + actual fun margin(value: SizeValue) = + styleScope.margin(value.platformValue) } diff --git a/compose-multiplatform-common/src/jvmMain/kotlin/com/huanshankeji/compose/ui/ModifierOrAttrsScopeJvm.kt b/compose-multiplatform-common/src/jvmMain/kotlin/com/huanshankeji/compose/ui/ModifierOrAttrsScopeJvm.kt index b5967d0e..88b59ee5 100644 --- a/compose-multiplatform-common/src/jvmMain/kotlin/com/huanshankeji/compose/ui/ModifierOrAttrsScopeJvm.kt +++ b/compose-multiplatform-common/src/jvmMain/kotlin/com/huanshankeji/compose/ui/ModifierOrAttrsScopeJvm.kt @@ -30,7 +30,7 @@ actual class ModifierOrAttrsScope(modifier: Modifier) { } actual class StyleScope(val modifierOrAttrsScope: ModifierOrAttrsScope<*>) { - actual fun padding(value: SizeValue) = modifierOrAttrsScope.modify { + actual fun margin(value: SizeValue) = modifierOrAttrsScope.modify { padding(value.platformValue) } } diff --git a/demo/src/commonMain/kotlin/com/huanshankeji/compose/material/demo/Composables.kt b/demo/src/commonMain/kotlin/com/huanshankeji/compose/material/demo/Composables.kt index 3d93e9a1..da148784 100644 --- a/demo/src/commonMain/kotlin/com/huanshankeji/compose/material/demo/Composables.kt +++ b/demo/src/commonMain/kotlin/com/huanshankeji/compose/material/demo/Composables.kt @@ -21,7 +21,7 @@ fun App() { }) { Card({ style { - padding(16.dpOrPx) + margin(16.dpOrPx) } }) { Column { @@ -40,7 +40,7 @@ fun App() { Box({ style { - padding(16.dpOrPx) + margin(16.dpOrPx) } }) { List { From 83ce685e1043ea387a7208183c18aa403766a1a8 Mon Sep 17 00:00:00 2001 From: Shreck Ye Date: Tue, 13 Dec 2022 18:43:29 +0800 Subject: [PATCH 19/34] Add a `StyleScope.padding` placeholder and update the demo code --- .../com/huanshankeji/compose/ui/ModifierOrAttrsScope.kt | 9 +++++++++ .../huanshankeji/compose/material/demo/Composables.kt | 6 +++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/compose-multiplatform-common/src/commonMain/kotlin/com/huanshankeji/compose/ui/ModifierOrAttrsScope.kt b/compose-multiplatform-common/src/commonMain/kotlin/com/huanshankeji/compose/ui/ModifierOrAttrsScope.kt index 95ebe3f9..36181bce 100644 --- a/compose-multiplatform-common/src/commonMain/kotlin/com/huanshankeji/compose/ui/ModifierOrAttrsScope.kt +++ b/compose-multiplatform-common/src/commonMain/kotlin/com/huanshankeji/compose/ui/ModifierOrAttrsScope.kt @@ -15,6 +15,15 @@ expect class StyleScope { fun margin(value: SizeValue) } +private const val PADDING_MESSAGE = + "This function is a placeholder for code completion. " + + "Use `margin` to add space around the composable, which is equivalent to `Modifier.padding`. " + + "Set `margin` in the inner composable to add inner padding." + +@Deprecated(PADDING_MESSAGE) +fun StyleScope.padding(value: SizeValue): Unit = + throw NotImplementedError(PADDING_MESSAGE) + /* /** An alternative immutable design like [Modifier]. */ expect class ModifierOrAttrsImmutable { diff --git a/demo/src/commonMain/kotlin/com/huanshankeji/compose/material/demo/Composables.kt b/demo/src/commonMain/kotlin/com/huanshankeji/compose/material/demo/Composables.kt index da148784..f9c193a0 100644 --- a/demo/src/commonMain/kotlin/com/huanshankeji/compose/material/demo/Composables.kt +++ b/demo/src/commonMain/kotlin/com/huanshankeji/compose/material/demo/Composables.kt @@ -24,7 +24,11 @@ fun App() { margin(16.dpOrPx) } }) { - Column { + Column({ + style { + margin(16.dpOrPx) + } + }) { BasicText("basic text") Text("Material text") From 600973c3ddd13ced15c442daca8f9a8d328cf80b Mon Sep 17 00:00:00 2001 From: Shreck Ye Date: Tue, 13 Dec 2022 23:48:49 +0800 Subject: [PATCH 20/34] Support different types of buttons and make `Button` default to `Contained` --- .../huanshankeji/compose/material/Button.kt | 5 +++++ .../huanshankeji/compose/material/Button.kt | 21 +++++++++++++++---- .../huanshankeji/compose/material/Button.kt | 15 +++++++++++-- 3 files changed, 35 insertions(+), 6 deletions(-) diff --git a/compose-multiplatform-material/src/commonMain/kotlin/com/huanshankeji/compose/material/Button.kt b/compose-multiplatform-material/src/commonMain/kotlin/com/huanshankeji/compose/material/Button.kt index b2ba102a..bfacad6a 100644 --- a/compose-multiplatform-material/src/commonMain/kotlin/com/huanshankeji/compose/material/Button.kt +++ b/compose-multiplatform-material/src/commonMain/kotlin/com/huanshankeji/compose/material/Button.kt @@ -11,9 +11,14 @@ expect /*value*/ class ButtonScope { expect abstract class ButtonElement : Element +enum class ButtonType { + Contained, Outlined, Text +} + @Composable expect fun Button( onClick: () -> Unit, + buttonType: ButtonType = ButtonType.Contained, modifierOrAttrs: ModifierOrAttrs = null, content: @Composable ButtonScope.() -> Unit ) diff --git a/compose-multiplatform-material/src/jsMain/kotlin/com/huanshankeji/compose/material/Button.kt b/compose-multiplatform-material/src/jsMain/kotlin/com/huanshankeji/compose/material/Button.kt index 38c0878d..2da15aa6 100644 --- a/compose-multiplatform-material/src/jsMain/kotlin/com/huanshankeji/compose/material/Button.kt +++ b/compose-multiplatform-material/src/jsMain/kotlin/com/huanshankeji/compose/material/Button.kt @@ -1,6 +1,7 @@ package com.huanshankeji.compose.material import androidx.compose.runtime.Composable +import com.huanshankeji.compose.material.ButtonType.* import com.huanshankeji.compose.ui.ModifierOrAttrs import com.huanshankeji.compose.ui.toAttrs import com.huanshankeji.compose.web.attributes.attrs @@ -8,6 +9,7 @@ import com.huanshankeji.compose.web.attributes.plus import dev.petuska.kmdc.button.Label import dev.petuska.kmdc.button.MDCButton import dev.petuska.kmdc.button.MDCButtonScope +import dev.petuska.kmdc.button.MDCButtonType import org.w3c.dom.HTMLButtonElement actual class ButtonScope(val mdcButtonScope: MDCButtonScope) { @@ -18,13 +20,24 @@ actual class ButtonScope(val mdcButtonScope: MDCButtonScope) actual typealias ButtonElement = HTMLButtonElement +fun ButtonType.toMDCButtonType() = + when (this) { + Contained -> MDCButtonType.Raised + Outlined -> MDCButtonType.Outlined + Text -> MDCButtonType.Text + } + @Composable actual fun Button( - onClick: () -> Unit, modifierOrAttrs: ModifierOrAttrs, content: @Composable ButtonScope.() -> Unit + onClick: () -> Unit, + buttonType: ButtonType, + modifierOrAttrs: ModifierOrAttrs, + content: @Composable ButtonScope.() -> Unit ) = - MDCButton(attrs = attrs { - onClick { onClick() } - } + modifierOrAttrs.toAttrs()) { + MDCButton(buttonType.toMDCButtonType(), + attrs = attrs { + onClick { onClick() } + } + modifierOrAttrs.toAttrs()) { ButtonScope(this).content() } diff --git a/compose-multiplatform-material/src/jvmMain/kotlin/com/huanshankeji/compose/material/Button.kt b/compose-multiplatform-material/src/jvmMain/kotlin/com/huanshankeji/compose/material/Button.kt index abb78391..64f74a50 100644 --- a/compose-multiplatform-material/src/jvmMain/kotlin/com/huanshankeji/compose/material/Button.kt +++ b/compose-multiplatform-material/src/jvmMain/kotlin/com/huanshankeji/compose/material/Button.kt @@ -1,7 +1,10 @@ package com.huanshankeji.compose.material import androidx.compose.foundation.layout.RowScope +import androidx.compose.material.OutlinedButton +import androidx.compose.material.TextButton import androidx.compose.runtime.Composable +import com.huanshankeji.compose.material.ButtonType.* import com.huanshankeji.compose.ui.Element import com.huanshankeji.compose.ui.ModifierOrAttrs import com.huanshankeji.compose.ui.toModifier @@ -17,7 +20,15 @@ actual abstract class ButtonElement : Element() @Composable actual fun Button( onClick: () -> Unit, + buttonType: ButtonType, modifierOrAttrs: ModifierOrAttrs, content: @Composable ButtonScope.() -> Unit -) = - androidx.compose.material.Button(onClick, modifierOrAttrs.toModifier()) { ButtonScope(this).content() } +) { + val modifier = modifierOrAttrs.toModifier() + val androidxContent: @Composable RowScope.() -> Unit = { ButtonScope(this).content() } + when (buttonType) { + Contained -> androidx.compose.material.Button(onClick, content = androidxContent) + Outlined -> OutlinedButton(onClick, content = androidxContent) + Text -> TextButton(onClick, content = androidxContent) + } +} From 218fc66053673ec5a7decc10df2bc1e54d185fed Mon Sep 17 00:00:00 2001 From: Shreck Ye Date: Wed, 14 Dec 2022 19:12:55 +0800 Subject: [PATCH 21/34] Use `modifierOrAttrs` in `Column` and `Row` in `jsMain` --- .../jsMain/kotlin/com/huanshankeji/compose/layout/Column.kt | 4 ++-- .../src/jsMain/kotlin/com/huanshankeji/compose/layout/Row.kt | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/compose-multiplatform-common/src/jsMain/kotlin/com/huanshankeji/compose/layout/Column.kt b/compose-multiplatform-common/src/jsMain/kotlin/com/huanshankeji/compose/layout/Column.kt index 29ac531d..2be02daa 100644 --- a/compose-multiplatform-common/src/jsMain/kotlin/com/huanshankeji/compose/layout/Column.kt +++ b/compose-multiplatform-common/src/jsMain/kotlin/com/huanshankeji/compose/layout/Column.kt @@ -2,6 +2,7 @@ package com.huanshankeji.compose.layout import androidx.compose.runtime.Composable import com.huanshankeji.compose.ui.ModifierOrAttrs +import com.huanshankeji.compose.ui.toAttrs import org.jetbrains.compose.web.dom.ElementScope import org.w3c.dom.HTMLDivElement @@ -15,7 +16,6 @@ actual interface ColumnScope { @Composable actual fun Column(modifierOrAttrs: ModifierOrAttrs, content: @Composable ColumnScope.() -> Unit) = - // TODO: `modifierOrAttrs` not used yet - com.huanshankeji.compose.web.Column { + com.huanshankeji.compose.web.Column(modifierOrAttrs.toAttrs()) { ColumnScope.Impl(this).content() } diff --git a/compose-multiplatform-common/src/jsMain/kotlin/com/huanshankeji/compose/layout/Row.kt b/compose-multiplatform-common/src/jsMain/kotlin/com/huanshankeji/compose/layout/Row.kt index 4dc97e1f..920fb2ad 100644 --- a/compose-multiplatform-common/src/jsMain/kotlin/com/huanshankeji/compose/layout/Row.kt +++ b/compose-multiplatform-common/src/jsMain/kotlin/com/huanshankeji/compose/layout/Row.kt @@ -2,6 +2,7 @@ package com.huanshankeji.compose.layout import androidx.compose.runtime.Composable import com.huanshankeji.compose.ui.ModifierOrAttrs +import com.huanshankeji.compose.ui.toAttrs import org.jetbrains.compose.web.dom.ElementScope import org.w3c.dom.HTMLDivElement @@ -15,7 +16,6 @@ actual interface RowScope { @Composable actual fun Row(modifierOrAttrs: ModifierOrAttrs, content: @Composable RowScope.() -> Unit) = - // TODO: `modifierOrAttrs` not used yet - com.huanshankeji.compose.web.Row { + com.huanshankeji.compose.web.Row(modifierOrAttrs.toAttrs()) { RowScope.Impl(this).content() } From dc55abe2dc47222c9965b4f6f8fce802494a17f0 Mon Sep 17 00:00:00 2001 From: Shreck Ye Date: Wed, 14 Dec 2022 19:16:34 +0800 Subject: [PATCH 22/34] Fix a bug introduced in commit 600973c3ddd13ced15c442daca8f9a8d328cf80b that `modifier` is not used in `Button` in `jvmMain` --- .../kotlin/com/huanshankeji/compose/material/Button.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/compose-multiplatform-material/src/jvmMain/kotlin/com/huanshankeji/compose/material/Button.kt b/compose-multiplatform-material/src/jvmMain/kotlin/com/huanshankeji/compose/material/Button.kt index 64f74a50..b81fb9a7 100644 --- a/compose-multiplatform-material/src/jvmMain/kotlin/com/huanshankeji/compose/material/Button.kt +++ b/compose-multiplatform-material/src/jvmMain/kotlin/com/huanshankeji/compose/material/Button.kt @@ -27,8 +27,8 @@ actual fun Button( val modifier = modifierOrAttrs.toModifier() val androidxContent: @Composable RowScope.() -> Unit = { ButtonScope(this).content() } when (buttonType) { - Contained -> androidx.compose.material.Button(onClick, content = androidxContent) - Outlined -> OutlinedButton(onClick, content = androidxContent) - Text -> TextButton(onClick, content = androidxContent) + Contained -> androidx.compose.material.Button(onClick, modifier, content = androidxContent) + Outlined -> OutlinedButton(onClick, modifier, content = androidxContent) + Text -> TextButton(onClick, modifier, content = androidxContent) } } From 4845e36827a9605d3c4f26571b2a833c4aad9efd Mon Sep 17 00:00:00 2001 From: Shreck Ye Date: Wed, 14 Dec 2022 20:06:51 +0800 Subject: [PATCH 23/34] Update README.md --- README.md | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 39297a73..5c29275b 100644 --- a/README.md +++ b/README.md @@ -6,9 +6,31 @@ We try to make the styles of the composable components follow those of the deskt Visual consistency across different platforms is not guaranteed. -There is no documentation for this project yet. Check out the demo project on how to use the components. +This project is prototype and there is no documentation yet. Check out [the demo project](demo) on how to use the components. + + ## Supported components +### Common (Foundation) components + +- `BasicText` +- `RawText` + +#### Layouts + +- `Box` +- `Column` +- `Row` + +### Material components + - `Button` +- `Card` +- `Icon` +- `IconButton` +- `List`/`LazyColumn` (visually inconsistent) +- `Text`/`MaterialText` - `TopAppBarScaffold` From 52c3cd7714d90da855928b3a74e17f0c529e23fc Mon Sep 17 00:00:00 2001 From: Shreck Ye Date: Wed, 14 Dec 2022 22:30:59 +0800 Subject: [PATCH 24/34] Add `height` and `width` in `StyleScope` There is a bug that the list extends beyond the card in the web demo. --- .../huanshankeji/compose/ui/ModifierOrAttrsScope.kt | 2 ++ .../huanshankeji/compose/ui/ModifierOrAttrsScope.kt | 8 ++++++++ .../huanshankeji/compose/ui/ModifierOrAttrsScopeJvm.kt | 10 ++++++++++ .../huanshankeji/compose/material/demo/Composables.kt | 1 + 4 files changed, 21 insertions(+) diff --git a/compose-multiplatform-common/src/commonMain/kotlin/com/huanshankeji/compose/ui/ModifierOrAttrsScope.kt b/compose-multiplatform-common/src/commonMain/kotlin/com/huanshankeji/compose/ui/ModifierOrAttrsScope.kt index 36181bce..63a4c6cf 100644 --- a/compose-multiplatform-common/src/commonMain/kotlin/com/huanshankeji/compose/ui/ModifierOrAttrsScope.kt +++ b/compose-multiplatform-common/src/commonMain/kotlin/com/huanshankeji/compose/ui/ModifierOrAttrsScope.kt @@ -13,6 +13,8 @@ expect class ModifierOrAttrsScope { expect class StyleScope { fun margin(value: SizeValue) + fun height(value: SizeValue) + fun width(value: SizeValue) } private const val PADDING_MESSAGE = diff --git a/compose-multiplatform-common/src/jsMain/kotlin/com/huanshankeji/compose/ui/ModifierOrAttrsScope.kt b/compose-multiplatform-common/src/jsMain/kotlin/com/huanshankeji/compose/ui/ModifierOrAttrsScope.kt index 60cea914..ea5db538 100644 --- a/compose-multiplatform-common/src/jsMain/kotlin/com/huanshankeji/compose/ui/ModifierOrAttrsScope.kt +++ b/compose-multiplatform-common/src/jsMain/kotlin/com/huanshankeji/compose/ui/ModifierOrAttrsScope.kt @@ -2,7 +2,9 @@ package com.huanshankeji.compose.ui import com.huanshankeji.compose.ui.unit.SizeValue import org.jetbrains.compose.web.attributes.AttrsScope +import org.jetbrains.compose.web.css.height import org.jetbrains.compose.web.css.margin +import org.jetbrains.compose.web.css.width import org.jetbrains.compose.web.dom.AttrBuilderContext import org.w3c.dom.HTMLElement @@ -22,4 +24,10 @@ actual class ModifierOrAttrsScope(val attrsScope: AttrsS actual class StyleScope(val styleScope: org.jetbrains.compose.web.css.StyleScope) { actual fun margin(value: SizeValue) = styleScope.margin(value.platformValue) + + actual fun height(value: SizeValue) = + styleScope.height(value.platformValue) + + actual fun width(value: SizeValue) = + styleScope.width(value.platformValue) } diff --git a/compose-multiplatform-common/src/jvmMain/kotlin/com/huanshankeji/compose/ui/ModifierOrAttrsScopeJvm.kt b/compose-multiplatform-common/src/jvmMain/kotlin/com/huanshankeji/compose/ui/ModifierOrAttrsScopeJvm.kt index 88b59ee5..43a927de 100644 --- a/compose-multiplatform-common/src/jvmMain/kotlin/com/huanshankeji/compose/ui/ModifierOrAttrsScopeJvm.kt +++ b/compose-multiplatform-common/src/jvmMain/kotlin/com/huanshankeji/compose/ui/ModifierOrAttrsScopeJvm.kt @@ -1,6 +1,8 @@ package com.huanshankeji.compose.ui +import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width import androidx.compose.ui.Modifier import com.huanshankeji.compose.ui.unit.SizeValue @@ -33,4 +35,12 @@ actual class StyleScope(val modifierOrAttrsScope: ModifierOrAttrsScope<*>) { actual fun margin(value: SizeValue) = modifierOrAttrsScope.modify { padding(value.platformValue) } + + actual fun height(value: SizeValue) = modifierOrAttrsScope.modify { + height(value.platformValue) + } + + actual fun width(value: SizeValue) = modifierOrAttrsScope.modify { + width(value.platformValue) + } } diff --git a/demo/src/commonMain/kotlin/com/huanshankeji/compose/material/demo/Composables.kt b/demo/src/commonMain/kotlin/com/huanshankeji/compose/material/demo/Composables.kt index f9c193a0..13e3d84c 100644 --- a/demo/src/commonMain/kotlin/com/huanshankeji/compose/material/demo/Composables.kt +++ b/demo/src/commonMain/kotlin/com/huanshankeji/compose/material/demo/Composables.kt @@ -22,6 +22,7 @@ fun App() { Card({ style { margin(16.dpOrPx) + height(400.dpOrPx) } }) { Column({ From cf31532669046d1316741dbdfd6289dc03f46e09 Mon Sep 17 00:00:00 2001 From: Shreck Ye Date: Thu, 15 Dec 2022 01:40:35 +0800 Subject: [PATCH 25/34] Support `FillMax` and `FitContent` and make `Card` default to `FitContent` on JS --- .../compose/ui/ModifierOrAttrsScope.kt | 35 +++++++++++++++---- .../com/huanshankeji/compose/ui/unit/Sizes.kt | 13 +++++-- .../compose/ui/ModifierOrAttrsScope.kt | 29 +++++++++++---- .../com/huanshankeji/compose/ui/unit/Sizes.kt | 8 ++--- .../compose/ui/ModifierOrAttrsScopeJvm.kt | 24 +++++++++---- .../com/huanshankeji/compose/ui/unit/Sizes.kt | 8 ++--- .../com/huanshankeji/compose/material/Card.kt | 7 +++- .../compose/material/demo/Composables.kt | 1 + 8 files changed, 93 insertions(+), 32 deletions(-) diff --git a/compose-multiplatform-common/src/commonMain/kotlin/com/huanshankeji/compose/ui/ModifierOrAttrsScope.kt b/compose-multiplatform-common/src/commonMain/kotlin/com/huanshankeji/compose/ui/ModifierOrAttrsScope.kt index 63a4c6cf..2d4f5be5 100644 --- a/compose-multiplatform-common/src/commonMain/kotlin/com/huanshankeji/compose/ui/ModifierOrAttrsScope.kt +++ b/compose-multiplatform-common/src/commonMain/kotlin/com/huanshankeji/compose/ui/ModifierOrAttrsScope.kt @@ -1,29 +1,52 @@ package com.huanshankeji.compose.ui //import androidx.compose.ui.Modifier -import com.huanshankeji.compose.ui.unit.SizeValue +import com.huanshankeji.compose.ui.unit.NumericSize +import com.huanshankeji.compose.ui.unit.Size + +typealias NotNullModifierOrAttrs = ModifierOrAttrsScope.() -> Unit +typealias ModifierOrAttrs = NotNullModifierOrAttrs? + +@Suppress("NOTHING_TO_INLINE") +inline fun modifierOrAttrs(noinline modifierOrAttrs: NotNullModifierOrAttrs) = + modifierOrAttrs + +operator fun NotNullModifierOrAttrs.plus(other: ModifierOrAttrs): ModifierOrAttrs = + if (other === null) this + else { + { + this@plus() + other() + } + } -typealias ModifierOrAttrs = (ModifierOrAttrsScope.() -> Unit)? expect abstract class Element + expect class ModifierOrAttrsScope { fun style(builder: StyleScope.() -> Unit) } expect class StyleScope { - fun margin(value: SizeValue) - fun height(value: SizeValue) - fun width(value: SizeValue) + fun margin(value: NumericSize) + fun height(value: Size) + fun width(value: Size) } +fun StyleScope.height(value: NumericSize) = + height(Size.Numeric(value)) + +fun StyleScope.width(value: NumericSize) = + width(Size.Numeric(value)) + private const val PADDING_MESSAGE = "This function is a placeholder for code completion. " + "Use `margin` to add space around the composable, which is equivalent to `Modifier.padding`. " + "Set `margin` in the inner composable to add inner padding." @Deprecated(PADDING_MESSAGE) -fun StyleScope.padding(value: SizeValue): Unit = +fun StyleScope.padding(value: NumericSize): Unit = throw NotImplementedError(PADDING_MESSAGE) /* diff --git a/compose-multiplatform-common/src/commonMain/kotlin/com/huanshankeji/compose/ui/unit/Sizes.kt b/compose-multiplatform-common/src/commonMain/kotlin/com/huanshankeji/compose/ui/unit/Sizes.kt index 44789cf3..3b29b12e 100644 --- a/compose-multiplatform-common/src/commonMain/kotlin/com/huanshankeji/compose/ui/unit/Sizes.kt +++ b/compose-multiplatform-common/src/commonMain/kotlin/com/huanshankeji/compose/ui/unit/Sizes.kt @@ -1,6 +1,13 @@ package com.huanshankeji.compose.ui.unit -expect abstract class SizeValue -expect class DpOrPxValue : SizeValue +expect abstract class NumericSize +expect class DpOrPx : NumericSize -expect val Int.dpOrPx: DpOrPxValue +expect val Int.dpOrPx: DpOrPx + + +sealed class Size { + class Numeric(val value: NumericSize) : Size() + object FillMax : Size() + object FitContent : Size() +} diff --git a/compose-multiplatform-common/src/jsMain/kotlin/com/huanshankeji/compose/ui/ModifierOrAttrsScope.kt b/compose-multiplatform-common/src/jsMain/kotlin/com/huanshankeji/compose/ui/ModifierOrAttrsScope.kt index ea5db538..a2b10dbe 100644 --- a/compose-multiplatform-common/src/jsMain/kotlin/com/huanshankeji/compose/ui/ModifierOrAttrsScope.kt +++ b/compose-multiplatform-common/src/jsMain/kotlin/com/huanshankeji/compose/ui/ModifierOrAttrsScope.kt @@ -1,9 +1,12 @@ package com.huanshankeji.compose.ui -import com.huanshankeji.compose.ui.unit.SizeValue +import com.huanshankeji.compose.ui.unit.NumericSize +import com.huanshankeji.compose.ui.unit.Size +import com.huanshankeji.compose.ui.unit.Size.* import org.jetbrains.compose.web.attributes.AttrsScope import org.jetbrains.compose.web.css.height import org.jetbrains.compose.web.css.margin +import org.jetbrains.compose.web.css.percent import org.jetbrains.compose.web.css.width import org.jetbrains.compose.web.dom.AttrBuilderContext import org.w3c.dom.HTMLElement @@ -22,12 +25,24 @@ actual class ModifierOrAttrsScope(val attrsScope: AttrsS } actual class StyleScope(val styleScope: org.jetbrains.compose.web.css.StyleScope) { - actual fun margin(value: SizeValue) = + actual fun margin(value: NumericSize) = styleScope.margin(value.platformValue) - actual fun height(value: SizeValue) = - styleScope.height(value.platformValue) - - actual fun width(value: SizeValue) = - styleScope.width(value.platformValue) + actual fun height(value: Size) = + styleScope.run { + when (value) { + FitContent -> property("height", "fit-content") + FillMax -> height(100.percent) + is Numeric -> height(value.value.platformValue) + } + } + + actual fun width(value: Size) = + styleScope.run { + when (value) { + FitContent -> property("width", "fit-content") + FillMax -> width(100.percent) + is Numeric -> width(value.value.platformValue) + } + } } diff --git a/compose-multiplatform-common/src/jsMain/kotlin/com/huanshankeji/compose/ui/unit/Sizes.kt b/compose-multiplatform-common/src/jsMain/kotlin/com/huanshankeji/compose/ui/unit/Sizes.kt index f61591f3..657d9fe7 100644 --- a/compose-multiplatform-common/src/jsMain/kotlin/com/huanshankeji/compose/ui/unit/Sizes.kt +++ b/compose-multiplatform-common/src/jsMain/kotlin/com/huanshankeji/compose/ui/unit/Sizes.kt @@ -5,8 +5,8 @@ import org.jetbrains.compose.web.css.CSSSizeValue import org.jetbrains.compose.web.css.CSSUnit import org.jetbrains.compose.web.css.px -actual abstract class SizeValue(val platformValue: CSSLengthOrPercentageValue) -actual class DpOrPxValue(platformValue: CSSSizeValue) : SizeValue(platformValue) +actual abstract class NumericSize(val platformValue: CSSLengthOrPercentageValue) +actual class DpOrPx(platformValue: CSSSizeValue) : NumericSize(platformValue) -actual val Int.dpOrPx: DpOrPxValue - get() = DpOrPxValue(this.px) +actual val Int.dpOrPx: DpOrPx + get() = DpOrPx(this.px) diff --git a/compose-multiplatform-common/src/jvmMain/kotlin/com/huanshankeji/compose/ui/ModifierOrAttrsScopeJvm.kt b/compose-multiplatform-common/src/jvmMain/kotlin/com/huanshankeji/compose/ui/ModifierOrAttrsScopeJvm.kt index 43a927de..ec18ea12 100644 --- a/compose-multiplatform-common/src/jvmMain/kotlin/com/huanshankeji/compose/ui/ModifierOrAttrsScopeJvm.kt +++ b/compose-multiplatform-common/src/jvmMain/kotlin/com/huanshankeji/compose/ui/ModifierOrAttrsScopeJvm.kt @@ -1,10 +1,12 @@ package com.huanshankeji.compose.ui +import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.width import androidx.compose.ui.Modifier -import com.huanshankeji.compose.ui.unit.SizeValue +import com.huanshankeji.compose.ui.unit.NumericSize +import com.huanshankeji.compose.ui.unit.Size +import com.huanshankeji.compose.ui.unit.Size.* fun ModifierOrAttrs.toModifier(): Modifier = this?.let { @@ -32,15 +34,23 @@ actual class ModifierOrAttrsScope(modifier: Modifier) { } actual class StyleScope(val modifierOrAttrsScope: ModifierOrAttrsScope<*>) { - actual fun margin(value: SizeValue) = modifierOrAttrsScope.modify { + actual fun margin(value: NumericSize) = modifierOrAttrsScope.modify { padding(value.platformValue) } - actual fun height(value: SizeValue) = modifierOrAttrsScope.modify { - height(value.platformValue) + actual fun height(value: Size) = modifierOrAttrsScope.modify { + when (value) { + FitContent -> this + FillMax -> fillMaxHeight() + is Numeric -> height(value.value.platformValue) + } } - actual fun width(value: SizeValue) = modifierOrAttrsScope.modify { - width(value.platformValue) + actual fun width(value: Size) = modifierOrAttrsScope.modify { + when (value) { + FitContent -> this + FillMax -> fillMaxHeight() + is Numeric -> height(value.value.platformValue) + } } } diff --git a/compose-multiplatform-common/src/jvmMain/kotlin/com/huanshankeji/compose/ui/unit/Sizes.kt b/compose-multiplatform-common/src/jvmMain/kotlin/com/huanshankeji/compose/ui/unit/Sizes.kt index 4dbf8563..c4bf92e4 100644 --- a/compose-multiplatform-common/src/jvmMain/kotlin/com/huanshankeji/compose/ui/unit/Sizes.kt +++ b/compose-multiplatform-common/src/jvmMain/kotlin/com/huanshankeji/compose/ui/unit/Sizes.kt @@ -3,8 +3,8 @@ package com.huanshankeji.compose.ui.unit import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp -actual abstract class SizeValue(val platformValue: Dp) -actual class DpOrPxValue(platformValue: Dp) : SizeValue(platformValue) +actual abstract class NumericSize(val platformValue: Dp) +actual class DpOrPx(platformValue: Dp) : NumericSize(platformValue) -actual val Int.dpOrPx: DpOrPxValue - get() = DpOrPxValue(this.dp) +actual val Int.dpOrPx: DpOrPx + get() = DpOrPx(this.dp) diff --git a/compose-multiplatform-material/src/jsMain/kotlin/com/huanshankeji/compose/material/Card.kt b/compose-multiplatform-material/src/jsMain/kotlin/com/huanshankeji/compose/material/Card.kt index 1e5f9d68..2ac529c1 100644 --- a/compose-multiplatform-material/src/jsMain/kotlin/com/huanshankeji/compose/material/Card.kt +++ b/compose-multiplatform-material/src/jsMain/kotlin/com/huanshankeji/compose/material/Card.kt @@ -2,7 +2,10 @@ package com.huanshankeji.compose.material import androidx.compose.runtime.Composable import com.huanshankeji.compose.ui.ModifierOrAttrs +import com.huanshankeji.compose.ui.modifierOrAttrs +import com.huanshankeji.compose.ui.plus import com.huanshankeji.compose.ui.toAttrs +import com.huanshankeji.compose.ui.unit.Size import dev.petuska.kmdc.card.MDCCard import org.w3c.dom.HTMLDivElement @@ -10,4 +13,6 @@ actual typealias CardElement = HTMLDivElement @Composable actual fun Card(modifierOrAttrs: ModifierOrAttrs, content: @Composable () -> Unit) = - MDCCard(attrs = modifierOrAttrs.toAttrs()) { content() } + MDCCard(attrs = (modifierOrAttrs { + style { width(Size.FitContent) } + } + modifierOrAttrs).toAttrs()) { content() } diff --git a/demo/src/commonMain/kotlin/com/huanshankeji/compose/material/demo/Composables.kt b/demo/src/commonMain/kotlin/com/huanshankeji/compose/material/demo/Composables.kt index 13e3d84c..20777f67 100644 --- a/demo/src/commonMain/kotlin/com/huanshankeji/compose/material/demo/Composables.kt +++ b/demo/src/commonMain/kotlin/com/huanshankeji/compose/material/demo/Composables.kt @@ -7,6 +7,7 @@ import com.huanshankeji.compose.layout.Column import com.huanshankeji.compose.layout.Row import com.huanshankeji.compose.material.* import com.huanshankeji.compose.material.icon.MaterialIcons +import com.huanshankeji.compose.ui.height import com.huanshankeji.compose.ui.unit.dpOrPx @OptIn(ConfusableTextApi::class) From ebc3db49319e387a9de020b390a3a372f2cb15ec Mon Sep 17 00:00:00 2001 From: Shreck Ye Date: Fri, 30 Dec 2022 22:21:13 +0800 Subject: [PATCH 26/34] Bump Compose to 1.2.2 --- buildSrc/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index 3aa580bc..3829bd98 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -10,7 +10,7 @@ repositories { dependencies { implementation(kotlin("gradle-plugin", "1.7.20")) - implementation("org.jetbrains.compose:compose-gradle-plugin:1.2.1") + implementation("org.jetbrains.compose:compose-gradle-plugin:1.2.2") implementation("com.huanshankeji.team:gradle-plugins:0.3.2") { exclude("org.jetbrains.kotlin") } From 51f105f62f08cf3ee339606ccbd42fe2d3d4768c Mon Sep 17 00:00:00 2001 From: Shreck Ye Date: Tue, 3 Jan 2023 17:40:36 +0800 Subject: [PATCH 27/34] Add a TODO comment for the snapshot version --- buildSrc/src/main/kotlin/VersionsAndDependencies.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buildSrc/src/main/kotlin/VersionsAndDependencies.kt b/buildSrc/src/main/kotlin/VersionsAndDependencies.kt index bd01fb62..dc5b5452 100644 --- a/buildSrc/src/main/kotlin/VersionsAndDependencies.kt +++ b/buildSrc/src/main/kotlin/VersionsAndDependencies.kt @@ -1,3 +1,3 @@ object DependencyVersions { - val huanshankejiComposeWeb = "0.2.0-SNAPSHOT" + val huanshankejiComposeWeb = "0.2.0-SNAPSHOT" // TODO: don't use a snapshot version in a main branch } From 0ebd4fa211a5ba6bb1889c0ddc213f4102046b03 Mon Sep 17 00:00:00 2001 From: Shreck Ye Date: Fri, 6 Jan 2023 20:01:28 +0800 Subject: [PATCH 28/34] Partially resolve the issue that `List`/`ScrollableList` overflows in `:demo` by adding `overflow-y` to `List`/`ScrollableList` and setting a fixed height in `:demo` Some other miscellaneous changes: 1. Make `List` scrollable on web by adding `overflow-y: auto` to it and rename it to `ScrollableList` 1. Try resolving the issue that an expandable scrollable element on web (with `overflow-y` set to `scroll` or `auto`) without `height`/`max-height` set overflows in a nested `div` without success 1. Rename `Composables.kt` to `App.kt` in `:demo` 1. Fix a bug in `StyleScope`.width` that `Modifier.height` is called in it 1. Update README.md --- README.md | 14 +++++++++----- .../kotlin/com/huanshankeji/compose/layout/Box.kt | 10 +++++++++- .../compose/ui/ModifierOrAttrsScope.kt | 7 +++++-- .../compose/ui/ModifierOrAttrsScopeJvm.kt | 3 ++- .../compose/material/ListAndLazyColumn.kt | 6 +++--- .../com/huanshankeji/compose/material/Card.kt | 13 +++++++------ .../compose/material/ListAndLazyColumn.kt | 12 ++++++++++-- .../compose/material/ListAndLazyColumnJvm.kt | 2 +- .../material/demo/{Composables.kt => App.kt} | 11 +++++++++-- 9 files changed, 55 insertions(+), 23 deletions(-) rename demo/src/commonMain/kotlin/com/huanshankeji/compose/material/demo/{Composables.kt => App.kt} (88%) diff --git a/README.md b/README.md index 5c29275b..49557fb1 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,12 @@ # Compose Multiplatform Material wrappers -Some simple Compose Multiplatform Material Design component wrappers for desktop, Android, and web (mainly based on [KMDC](https://github.com/mpetuska/kmdc)) +Some simple Compose Multiplatform wrappers of common components, layouts, and Material Design components for desktop, +Android, and web (mainly based on [KMDC](https://github.com/mpetuska/kmdc)) -We try to make the styles of the composable components follow those of the desktop and Android ones in `com.huanshankeji.compose.material`, meanwhile being compatible with the Web APIs. However, only a subset of the composable arguments is supported due to the API differences and limitations of the web composables this project depends on. +We try to make the function types of the composable components follow those of the desktop and Android ones +in `androidx.compose.foundation` and `androidx.compose.material`, meanwhile being compatible with the Web APIs. However, +only subsets of the composables and composable arguments are supported due to the API differences, limitations of the +web composables this project depends on, and our limited effort. Visual consistency across different platforms is not guaranteed. @@ -22,8 +26,8 @@ There is no plan to support Apple platforms until there is official support from #### Layouts - `Box` -- `Column` -- `Row` +- `Column` (via flexbox on web) +- `Row` (via flexbox on web) ### Material components @@ -31,6 +35,6 @@ There is no plan to support Apple platforms until there is official support from - `Card` - `Icon` - `IconButton` -- `List`/`LazyColumn` (visually inconsistent) +- `ScrollableList`/`LazyColumn` (visually inconsistent for now) - `Text`/`MaterialText` - `TopAppBarScaffold` diff --git a/compose-multiplatform-common/src/jsMain/kotlin/com/huanshankeji/compose/layout/Box.kt b/compose-multiplatform-common/src/jsMain/kotlin/com/huanshankeji/compose/layout/Box.kt index 35fd70fd..f1b3fbb9 100644 --- a/compose-multiplatform-common/src/jsMain/kotlin/com/huanshankeji/compose/layout/Box.kt +++ b/compose-multiplatform-common/src/jsMain/kotlin/com/huanshankeji/compose/layout/Box.kt @@ -3,6 +3,10 @@ package com.huanshankeji.compose.layout import androidx.compose.runtime.Composable import com.huanshankeji.compose.ui.ModifierOrAttrs import com.huanshankeji.compose.ui.toAttrs +import com.huanshankeji.compose.web.attributes.attrs +import com.huanshankeji.compose.web.attributes.plus +import com.huanshankeji.compose.web.css.FIT_CONTENT +import com.huanshankeji.compose.web.css.width import org.jetbrains.compose.web.dom.Div import org.jetbrains.compose.web.dom.ElementScope import org.w3c.dom.HTMLDivElement @@ -18,4 +22,8 @@ actual interface BoxScope { @Composable actual fun Box(modifierOrAttrs: ModifierOrAttrs, content: @Composable BoxScope.() -> Unit) = - Div(modifierOrAttrs.toAttrs()) { BoxScope.Impl(this).content() } + Div(attrs { + style { width(FIT_CONTENT) } + } + modifierOrAttrs.toAttrs()) { + BoxScope.Impl(this).content() + } diff --git a/compose-multiplatform-common/src/jsMain/kotlin/com/huanshankeji/compose/ui/ModifierOrAttrsScope.kt b/compose-multiplatform-common/src/jsMain/kotlin/com/huanshankeji/compose/ui/ModifierOrAttrsScope.kt index a2b10dbe..d992431e 100644 --- a/compose-multiplatform-common/src/jsMain/kotlin/com/huanshankeji/compose/ui/ModifierOrAttrsScope.kt +++ b/compose-multiplatform-common/src/jsMain/kotlin/com/huanshankeji/compose/ui/ModifierOrAttrsScope.kt @@ -3,6 +3,9 @@ package com.huanshankeji.compose.ui import com.huanshankeji.compose.ui.unit.NumericSize import com.huanshankeji.compose.ui.unit.Size import com.huanshankeji.compose.ui.unit.Size.* +import com.huanshankeji.compose.web.css.FIT_CONTENT +import com.huanshankeji.compose.web.css.height +import com.huanshankeji.compose.web.css.width import org.jetbrains.compose.web.attributes.AttrsScope import org.jetbrains.compose.web.css.height import org.jetbrains.compose.web.css.margin @@ -31,7 +34,7 @@ actual class StyleScope(val styleScope: org.jetbrains.compose.web.css.StyleScope actual fun height(value: Size) = styleScope.run { when (value) { - FitContent -> property("height", "fit-content") + FitContent -> height(FIT_CONTENT) FillMax -> height(100.percent) is Numeric -> height(value.value.platformValue) } @@ -40,7 +43,7 @@ actual class StyleScope(val styleScope: org.jetbrains.compose.web.css.StyleScope actual fun width(value: Size) = styleScope.run { when (value) { - FitContent -> property("width", "fit-content") + FitContent -> width(FIT_CONTENT) FillMax -> width(100.percent) is Numeric -> width(value.value.platformValue) } diff --git a/compose-multiplatform-common/src/jvmMain/kotlin/com/huanshankeji/compose/ui/ModifierOrAttrsScopeJvm.kt b/compose-multiplatform-common/src/jvmMain/kotlin/com/huanshankeji/compose/ui/ModifierOrAttrsScopeJvm.kt index ec18ea12..fd470380 100644 --- a/compose-multiplatform-common/src/jvmMain/kotlin/com/huanshankeji/compose/ui/ModifierOrAttrsScopeJvm.kt +++ b/compose-multiplatform-common/src/jvmMain/kotlin/com/huanshankeji/compose/ui/ModifierOrAttrsScopeJvm.kt @@ -3,6 +3,7 @@ package com.huanshankeji.compose.ui import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width import androidx.compose.ui.Modifier import com.huanshankeji.compose.ui.unit.NumericSize import com.huanshankeji.compose.ui.unit.Size @@ -50,7 +51,7 @@ actual class StyleScope(val modifierOrAttrsScope: ModifierOrAttrsScope<*>) { when (value) { FitContent -> this FillMax -> fillMaxHeight() - is Numeric -> height(value.value.platformValue) + is Numeric -> width(value.value.platformValue) } } } diff --git a/compose-multiplatform-material/src/commonMain/kotlin/com/huanshankeji/compose/material/ListAndLazyColumn.kt b/compose-multiplatform-material/src/commonMain/kotlin/com/huanshankeji/compose/material/ListAndLazyColumn.kt index 7323fa93..f831c56c 100644 --- a/compose-multiplatform-material/src/commonMain/kotlin/com/huanshankeji/compose/material/ListAndLazyColumn.kt +++ b/compose-multiplatform-material/src/commonMain/kotlin/com/huanshankeji/compose/material/ListAndLazyColumn.kt @@ -58,12 +58,12 @@ expect class HeaderScope @Composable -expect fun List(modifierOrAttrs: ModifierOrAttrs = null, content: ListScope.() -> Unit) +expect fun ScrollableList(modifierOrAttrs: ModifierOrAttrs = null, content: ListScope.() -> Unit) /** - * An alias for [List] that follows the name of [androidx.compose.foundation.lazy.LazyColumn]. + * An alias for [ScrollableList] that follows the name of [androidx.compose.foundation.lazy.LazyColumn]. * The current implementation is not actually lazy on web. */ @Composable fun LazyColumn(modifierOrAttrs: ModifierOrAttrs = null, content: ListScope.() -> Unit) = - List(modifierOrAttrs, content) + ScrollableList(modifierOrAttrs, content) diff --git a/compose-multiplatform-material/src/jsMain/kotlin/com/huanshankeji/compose/material/Card.kt b/compose-multiplatform-material/src/jsMain/kotlin/com/huanshankeji/compose/material/Card.kt index 2ac529c1..bee14c25 100644 --- a/compose-multiplatform-material/src/jsMain/kotlin/com/huanshankeji/compose/material/Card.kt +++ b/compose-multiplatform-material/src/jsMain/kotlin/com/huanshankeji/compose/material/Card.kt @@ -2,10 +2,11 @@ package com.huanshankeji.compose.material import androidx.compose.runtime.Composable import com.huanshankeji.compose.ui.ModifierOrAttrs -import com.huanshankeji.compose.ui.modifierOrAttrs -import com.huanshankeji.compose.ui.plus import com.huanshankeji.compose.ui.toAttrs -import com.huanshankeji.compose.ui.unit.Size +import com.huanshankeji.compose.web.attributes.attrs +import com.huanshankeji.compose.web.attributes.plus +import com.huanshankeji.compose.web.css.FIT_CONTENT +import com.huanshankeji.compose.web.css.width import dev.petuska.kmdc.card.MDCCard import org.w3c.dom.HTMLDivElement @@ -13,6 +14,6 @@ actual typealias CardElement = HTMLDivElement @Composable actual fun Card(modifierOrAttrs: ModifierOrAttrs, content: @Composable () -> Unit) = - MDCCard(attrs = (modifierOrAttrs { - style { width(Size.FitContent) } - } + modifierOrAttrs).toAttrs()) { content() } + MDCCard(attrs = attrs { + style { width(FIT_CONTENT) } + } + modifierOrAttrs.toAttrs()) { content() } diff --git a/compose-multiplatform-material/src/jsMain/kotlin/com/huanshankeji/compose/material/ListAndLazyColumn.kt b/compose-multiplatform-material/src/jsMain/kotlin/com/huanshankeji/compose/material/ListAndLazyColumn.kt index 387bd8ab..458e0285 100644 --- a/compose-multiplatform-material/src/jsMain/kotlin/com/huanshankeji/compose/material/ListAndLazyColumn.kt +++ b/compose-multiplatform-material/src/jsMain/kotlin/com/huanshankeji/compose/material/ListAndLazyColumn.kt @@ -3,12 +3,15 @@ package com.huanshankeji.compose.material import androidx.compose.runtime.Composable import com.huanshankeji.compose.ui.ModifierOrAttrs import com.huanshankeji.compose.ui.toAttrs +import com.huanshankeji.compose.web.attributes.attrs +import com.huanshankeji.compose.web.attributes.plus import dev.petuska.kmdc.list.MDCList import dev.petuska.kmdc.list.MDCListGroup import dev.petuska.kmdc.list.MDCListScope import dev.petuska.kmdc.list.Subheader import dev.petuska.kmdc.list.item.ListItem import dev.petuska.kmdc.list.item.MDCListItemScope +import org.jetbrains.compose.web.css.* import org.jetbrains.compose.web.dom.ElementScope import org.w3c.dom.HTMLHeadingElement import org.w3c.dom.HTMLLIElement @@ -75,7 +78,12 @@ actual class ItemScope(val mdcListItemScope: MDCListItemScope) actual class HeaderScope(val elementScope: ElementScope) @Composable -actual fun List(modifierOrAttrs: ModifierOrAttrs, content: ListScope.() -> Unit) = - MDCList(attrs = modifierOrAttrs.toAttrs()) { +actual fun ScrollableList(modifierOrAttrs: ModifierOrAttrs, content: ListScope.() -> Unit) = + MDCList(attrs = attrs { + style { + //overflowY("scroll") + overflowY("auto") + } + } + modifierOrAttrs.toAttrs()) { ListScope(this).ComposableRun(content) } diff --git a/compose-multiplatform-material/src/jvmMain/kotlin/com/huanshankeji/compose/material/ListAndLazyColumnJvm.kt b/compose-multiplatform-material/src/jvmMain/kotlin/com/huanshankeji/compose/material/ListAndLazyColumnJvm.kt index 1dc103c5..d83fa4c6 100644 --- a/compose-multiplatform-material/src/jvmMain/kotlin/com/huanshankeji/compose/material/ListAndLazyColumnJvm.kt +++ b/compose-multiplatform-material/src/jvmMain/kotlin/com/huanshankeji/compose/material/ListAndLazyColumnJvm.kt @@ -38,7 +38,7 @@ actual class ItemScope(val lazyItemScope: LazyItemScope) actual typealias HeaderScope = ItemScope @Composable -actual fun List(modifierOrAttrs: ModifierOrAttrs, content: ListScope.() -> Unit) = +actual fun ScrollableList(modifierOrAttrs: ModifierOrAttrs, content: ListScope.() -> Unit) = androidx.compose.foundation.lazy.LazyColumn(modifierOrAttrs.toModifier()) { ListScope(this).content() } diff --git a/demo/src/commonMain/kotlin/com/huanshankeji/compose/material/demo/Composables.kt b/demo/src/commonMain/kotlin/com/huanshankeji/compose/material/demo/App.kt similarity index 88% rename from demo/src/commonMain/kotlin/com/huanshankeji/compose/material/demo/Composables.kt rename to demo/src/commonMain/kotlin/com/huanshankeji/compose/material/demo/App.kt index 20777f67..383c8a95 100644 --- a/demo/src/commonMain/kotlin/com/huanshankeji/compose/material/demo/Composables.kt +++ b/demo/src/commonMain/kotlin/com/huanshankeji/compose/material/demo/App.kt @@ -9,6 +9,7 @@ import com.huanshankeji.compose.material.* import com.huanshankeji.compose.material.icon.MaterialIcons import com.huanshankeji.compose.ui.height import com.huanshankeji.compose.ui.unit.dpOrPx +import com.huanshankeji.compose.ui.width @OptIn(ConfusableTextApi::class) @Composable @@ -23,7 +24,9 @@ fun App() { Card({ style { margin(16.dpOrPx) - height(400.dpOrPx) + val size = 400.dpOrPx + height(size) + width(size) } }) { Column({ @@ -49,7 +52,11 @@ fun App() { margin(16.dpOrPx) } }) { - List { + ScrollableList({ + style { + height(200.dpOrPx) + } + }) { item { Text("Ungrouped item") } From 8ad4091e2d6335effd412da0062c49071dfc32ae Mon Sep 17 00:00:00 2001 From: Shreck Ye Date: Sat, 7 Jan 2023 02:59:14 +0800 Subject: [PATCH 29/34] Add the Maven Central badge which doesn't work yet --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 49557fb1..402fb212 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # Compose Multiplatform Material wrappers +[![Maven Central](https://img.shields.io/maven-central/v/com.huanshankeji/compose-multiplatform-material)](https://search.maven.org/artifact/com.huanshankeji/compose-multiplatform-material) + Some simple Compose Multiplatform wrappers of common components, layouts, and Material Design components for desktop, Android, and web (mainly based on [KMDC](https://github.com/mpetuska/kmdc)) From baa962d6b3fa24d8e830fb2d1bbbefc3dcef2bbf Mon Sep 17 00:00:00 2001 From: Shreck Ye Date: Mon, 9 Jan 2023 17:02:00 +0800 Subject: [PATCH 30/34] Implement borders and colors, and refactor sizes and update the demo --- .../compose/ui/ModifierOrAttrsScope.kt | 47 +++++++++++++---- .../huanshankeji/compose/ui/color/Color.kt | 16 ++++++ .../huanshankeji/compose/ui/color/Colors.kt | 10 ++++ .../com/huanshankeji/compose/ui/unit/Sizes.kt | 15 +++--- .../compose/ui/ModifierOrAttrsScope.kt | 29 +++++++---- .../huanshankeji/compose/ui/color/Color.kt | 16 ++++++ .../huanshankeji/compose/ui/color/Colors.kt | 12 +++++ .../com/huanshankeji/compose/ui/unit/Sizes.kt | 25 +++++++--- .../compose/ui/ModifierOrAttrsScopeJvm.kt | 50 +++++++++++++------ .../huanshankeji/compose/ui/color/ColorJvm.kt | 16 ++++++ .../huanshankeji/compose/ui/color/Colors.kt | 10 ++++ .../com/huanshankeji/compose/ui/unit/Sizes.kt | 19 ++++++- .../huanshankeji/compose/material/demo/App.kt | 31 +++++++++++- 13 files changed, 246 insertions(+), 50 deletions(-) create mode 100644 compose-multiplatform-common/src/commonMain/kotlin/com/huanshankeji/compose/ui/color/Color.kt create mode 100644 compose-multiplatform-common/src/commonMain/kotlin/com/huanshankeji/compose/ui/color/Colors.kt create mode 100644 compose-multiplatform-common/src/jsMain/kotlin/com/huanshankeji/compose/ui/color/Color.kt create mode 100644 compose-multiplatform-common/src/jsMain/kotlin/com/huanshankeji/compose/ui/color/Colors.kt create mode 100644 compose-multiplatform-common/src/jvmMain/kotlin/com/huanshankeji/compose/ui/color/ColorJvm.kt create mode 100644 compose-multiplatform-common/src/jvmMain/kotlin/com/huanshankeji/compose/ui/color/Colors.kt diff --git a/compose-multiplatform-common/src/commonMain/kotlin/com/huanshankeji/compose/ui/ModifierOrAttrsScope.kt b/compose-multiplatform-common/src/commonMain/kotlin/com/huanshankeji/compose/ui/ModifierOrAttrsScope.kt index 2d4f5be5..4de49220 100644 --- a/compose-multiplatform-common/src/commonMain/kotlin/com/huanshankeji/compose/ui/ModifierOrAttrsScope.kt +++ b/compose-multiplatform-common/src/commonMain/kotlin/com/huanshankeji/compose/ui/ModifierOrAttrsScope.kt @@ -1,8 +1,10 @@ package com.huanshankeji.compose.ui //import androidx.compose.ui.Modifier -import com.huanshankeji.compose.ui.unit.NumericSize -import com.huanshankeji.compose.ui.unit.Size +import com.huanshankeji.compose.ui.color.Color +import com.huanshankeji.compose.ui.unit.HeightOrWidth +import com.huanshankeji.compose.ui.unit.Length +import com.huanshankeji.compose.ui.unit.LengthOrPercentage typealias NotNullModifierOrAttrs = ModifierOrAttrsScope.() -> Unit typealias ModifierOrAttrs = NotNullModifierOrAttrs? @@ -28,17 +30,42 @@ expect class ModifierOrAttrsScope { fun style(builder: StyleScope.() -> Unit) } +/** + * Keep in mind that the functions in this class call functions in + * [org.jetbrains.compose.web.css.StyleScope] and [androidx.compose.ui.Modifier] under the hood + * so their visual results are not consistent. + * As different orders of `Modifier` function calls produce different results, + * different orders of function calls in this class produce different results on desktop and Android. + * They do produce the same results on web as long as no former property is overriden by a latter one, + * as different orders of CSS properties do in the HTML `style` attribute. + */ expect class StyleScope { - fun margin(value: NumericSize) - fun height(value: Size) - fun width(value: Size) + fun margin(value: LengthOrPercentage) + fun height(value: HeightOrWidth) + fun width(value: HeightOrWidth) + + fun backgroundColor(color: Color) + + /** + * Currently inconsistent, adds inner border on desktop and Android and outer padding on web. + */ + fun border(width: Length, color: Color) + + fun outerBorder(width: Length, color: Color) + + // TODO + /* + class CornerSize + + fun roundedCornerBorder(width: Length, color: Color, cornerRadius: CornerSize) + */ } -fun StyleScope.height(value: NumericSize) = - height(Size.Numeric(value)) +fun StyleScope.height(value: LengthOrPercentage) = + height(HeightOrWidth.Numeric(value)) -fun StyleScope.width(value: NumericSize) = - width(Size.Numeric(value)) +fun StyleScope.width(value: LengthOrPercentage) = + width(HeightOrWidth.Numeric(value)) private const val PADDING_MESSAGE = "This function is a placeholder for code completion. " + @@ -46,7 +73,7 @@ private const val PADDING_MESSAGE = "Set `margin` in the inner composable to add inner padding." @Deprecated(PADDING_MESSAGE) -fun StyleScope.padding(value: NumericSize): Unit = +fun StyleScope.padding(value: LengthOrPercentage): Unit = throw NotImplementedError(PADDING_MESSAGE) /* diff --git a/compose-multiplatform-common/src/commonMain/kotlin/com/huanshankeji/compose/ui/color/Color.kt b/compose-multiplatform-common/src/commonMain/kotlin/com/huanshankeji/compose/ui/color/Color.kt new file mode 100644 index 00000000..94f40b80 --- /dev/null +++ b/compose-multiplatform-common/src/commonMain/kotlin/com/huanshankeji/compose/ui/color/Color.kt @@ -0,0 +1,16 @@ +package com.huanshankeji.compose.ui.color + +expect class Color + +internal fun UByte.alphaToFloatRatio(): Float = + toFloat() / 255 + +internal fun Float.alphaToUByte(): UByte { + require(this in 0f..1f) + return (this * 255).toInt().toUByte() +} + +expect fun rgbaColor(red: UByte, green: UByte, blue: UByte, alpha: UByte): Color +expect fun rgbaColor(red: UByte, green: UByte, blue: UByte, alpha: Float): Color + +expect fun rgbColor(red: UByte, green: UByte, blue: UByte): Color diff --git a/compose-multiplatform-common/src/commonMain/kotlin/com/huanshankeji/compose/ui/color/Colors.kt b/compose-multiplatform-common/src/commonMain/kotlin/com/huanshankeji/compose/ui/color/Colors.kt new file mode 100644 index 00000000..bfc27795 --- /dev/null +++ b/compose-multiplatform-common/src/commonMain/kotlin/com/huanshankeji/compose/ui/color/Colors.kt @@ -0,0 +1,10 @@ +package com.huanshankeji.compose.ui.color + +expect object Colors { + val black: Color + val white: Color + val gray : Color + val red: Color + val green: Color + val blue: Color +} \ No newline at end of file diff --git a/compose-multiplatform-common/src/commonMain/kotlin/com/huanshankeji/compose/ui/unit/Sizes.kt b/compose-multiplatform-common/src/commonMain/kotlin/com/huanshankeji/compose/ui/unit/Sizes.kt index 3b29b12e..b9426f0e 100644 --- a/compose-multiplatform-common/src/commonMain/kotlin/com/huanshankeji/compose/ui/unit/Sizes.kt +++ b/compose-multiplatform-common/src/commonMain/kotlin/com/huanshankeji/compose/ui/unit/Sizes.kt @@ -1,13 +1,16 @@ package com.huanshankeji.compose.ui.unit -expect abstract class NumericSize -expect class DpOrPx : NumericSize +// Percentage is only supported on JS. +expect sealed interface LengthOrPercentage +expect sealed interface Length : LengthOrPercentage + +expect class DpOrPx : Length expect val Int.dpOrPx: DpOrPx -sealed class Size { - class Numeric(val value: NumericSize) : Size() - object FillMax : Size() - object FitContent : Size() +sealed class HeightOrWidth { + class Numeric(val value: LengthOrPercentage) : HeightOrWidth() + object FillMax : HeightOrWidth() + object FitContent : HeightOrWidth() } diff --git a/compose-multiplatform-common/src/jsMain/kotlin/com/huanshankeji/compose/ui/ModifierOrAttrsScope.kt b/compose-multiplatform-common/src/jsMain/kotlin/com/huanshankeji/compose/ui/ModifierOrAttrsScope.kt index d992431e..c98f373f 100644 --- a/compose-multiplatform-common/src/jsMain/kotlin/com/huanshankeji/compose/ui/ModifierOrAttrsScope.kt +++ b/compose-multiplatform-common/src/jsMain/kotlin/com/huanshankeji/compose/ui/ModifierOrAttrsScope.kt @@ -1,16 +1,15 @@ package com.huanshankeji.compose.ui -import com.huanshankeji.compose.ui.unit.NumericSize -import com.huanshankeji.compose.ui.unit.Size -import com.huanshankeji.compose.ui.unit.Size.* +import com.huanshankeji.compose.ui.color.Color +import com.huanshankeji.compose.ui.unit.HeightOrWidth +import com.huanshankeji.compose.ui.unit.HeightOrWidth.* +import com.huanshankeji.compose.ui.unit.Length +import com.huanshankeji.compose.ui.unit.LengthOrPercentage import com.huanshankeji.compose.web.css.FIT_CONTENT import com.huanshankeji.compose.web.css.height import com.huanshankeji.compose.web.css.width import org.jetbrains.compose.web.attributes.AttrsScope -import org.jetbrains.compose.web.css.height -import org.jetbrains.compose.web.css.margin -import org.jetbrains.compose.web.css.percent -import org.jetbrains.compose.web.css.width +import org.jetbrains.compose.web.css.* import org.jetbrains.compose.web.dom.AttrBuilderContext import org.w3c.dom.HTMLElement @@ -28,10 +27,10 @@ actual class ModifierOrAttrsScope(val attrsScope: AttrsS } actual class StyleScope(val styleScope: org.jetbrains.compose.web.css.StyleScope) { - actual fun margin(value: NumericSize) = + actual fun margin(value: LengthOrPercentage) = styleScope.margin(value.platformValue) - actual fun height(value: Size) = + actual fun height(value: HeightOrWidth) = styleScope.run { when (value) { FitContent -> height(FIT_CONTENT) @@ -40,7 +39,7 @@ actual class StyleScope(val styleScope: org.jetbrains.compose.web.css.StyleScope } } - actual fun width(value: Size) = + actual fun width(value: HeightOrWidth) = styleScope.run { when (value) { FitContent -> width(FIT_CONTENT) @@ -48,4 +47,14 @@ actual class StyleScope(val styleScope: org.jetbrains.compose.web.css.StyleScope is Numeric -> width(value.value.platformValue) } } + + + actual fun backgroundColor(color: Color) = + styleScope.backgroundColor(color.platformValue) + + actual fun border(width: Length, color: Color) = + styleScope.border(width.platformValue, LineStyle.Solid, color.platformValue) + + actual fun outerBorder(width: Length, color: Color) = + border(width, color) } diff --git a/compose-multiplatform-common/src/jsMain/kotlin/com/huanshankeji/compose/ui/color/Color.kt b/compose-multiplatform-common/src/jsMain/kotlin/com/huanshankeji/compose/ui/color/Color.kt new file mode 100644 index 00000000..333cd884 --- /dev/null +++ b/compose-multiplatform-common/src/jsMain/kotlin/com/huanshankeji/compose/ui/color/Color.kt @@ -0,0 +1,16 @@ +package com.huanshankeji.compose.ui.color + +import org.jetbrains.compose.web.css.CSSColorValue +import org.jetbrains.compose.web.css.rgb +import org.jetbrains.compose.web.css.rgba + +actual class Color(val platformValue: CSSColorValue) + +actual fun rgbaColor(red: UByte, green: UByte, blue: UByte, alpha: UByte): Color = + rgbaColor(red, green, blue, alpha.alphaToFloatRatio()) + +actual fun rgbaColor(red: UByte, green: UByte, blue: UByte, alpha: Float): Color = + Color(rgba(red.toInt(), green.toInt(), blue.toInt(), alpha)) + +actual fun rgbColor(red: UByte, green: UByte, blue: UByte): Color = + Color(rgb(red.toInt(), green.toInt(), blue.toInt())) diff --git a/compose-multiplatform-common/src/jsMain/kotlin/com/huanshankeji/compose/ui/color/Colors.kt b/compose-multiplatform-common/src/jsMain/kotlin/com/huanshankeji/compose/ui/color/Colors.kt new file mode 100644 index 00000000..de9dd0ba --- /dev/null +++ b/compose-multiplatform-common/src/jsMain/kotlin/com/huanshankeji/compose/ui/color/Colors.kt @@ -0,0 +1,12 @@ +package com.huanshankeji.compose.ui.color + +import org.jetbrains.compose.web.css.Color as CssColor + +actual object Colors { + actual val black = Color(CssColor.black) + actual val white = Color(CssColor.white) + actual val gray = Color(CssColor.gray) + actual val red = Color(CssColor.red) + actual val green = Color(CssColor.green) + actual val blue = Color(CssColor.blue) +} \ No newline at end of file diff --git a/compose-multiplatform-common/src/jsMain/kotlin/com/huanshankeji/compose/ui/unit/Sizes.kt b/compose-multiplatform-common/src/jsMain/kotlin/com/huanshankeji/compose/ui/unit/Sizes.kt index 657d9fe7..0b80f4ca 100644 --- a/compose-multiplatform-common/src/jsMain/kotlin/com/huanshankeji/compose/ui/unit/Sizes.kt +++ b/compose-multiplatform-common/src/jsMain/kotlin/com/huanshankeji/compose/ui/unit/Sizes.kt @@ -1,12 +1,25 @@ package com.huanshankeji.compose.ui.unit -import org.jetbrains.compose.web.css.CSSLengthOrPercentageValue -import org.jetbrains.compose.web.css.CSSSizeValue -import org.jetbrains.compose.web.css.CSSUnit -import org.jetbrains.compose.web.css.px +import org.jetbrains.compose.web.css.* -actual abstract class NumericSize(val platformValue: CSSLengthOrPercentageValue) -actual class DpOrPx(platformValue: CSSSizeValue) : NumericSize(platformValue) +// TODO: consider adding a platform value type parameter or making it an interface. +actual sealed interface LengthOrPercentage { + val platformValue: CSSLengthOrPercentageValue + + class Impl(override val platformValue: CSSLengthOrPercentageValue) : LengthOrPercentage +} + +actual sealed interface Length : LengthOrPercentage { + override val platformValue: CSSLengthValue + + class Impl(override val platformValue: CSSLengthValue) : Length +} + +// JS only +class Percentage(override val platformValue: CSSPercentageValue) : LengthOrPercentage + + +actual class DpOrPx(override val platformValue: CSSpxValue) : Length actual val Int.dpOrPx: DpOrPx get() = DpOrPx(this.px) diff --git a/compose-multiplatform-common/src/jvmMain/kotlin/com/huanshankeji/compose/ui/ModifierOrAttrsScopeJvm.kt b/compose-multiplatform-common/src/jvmMain/kotlin/com/huanshankeji/compose/ui/ModifierOrAttrsScopeJvm.kt index fd470380..eb12b924 100644 --- a/compose-multiplatform-common/src/jvmMain/kotlin/com/huanshankeji/compose/ui/ModifierOrAttrsScopeJvm.kt +++ b/compose-multiplatform-common/src/jvmMain/kotlin/com/huanshankeji/compose/ui/ModifierOrAttrsScopeJvm.kt @@ -1,13 +1,15 @@ package com.huanshankeji.compose.ui -import androidx.compose.foundation.layout.fillMaxHeight -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.width +import androidx.compose.foundation.background +import androidx.compose.foundation.border +import androidx.compose.foundation.layout.* import androidx.compose.ui.Modifier -import com.huanshankeji.compose.ui.unit.NumericSize -import com.huanshankeji.compose.ui.unit.Size -import com.huanshankeji.compose.ui.unit.Size.* +import com.huanshankeji.compose.ui.color.Color +import com.huanshankeji.compose.ui.unit.HeightOrWidth +import com.huanshankeji.compose.ui.unit.HeightOrWidth.* +import com.huanshankeji.compose.ui.unit.Length +import com.huanshankeji.compose.ui.unit.LengthOrPercentage +import com.huanshankeji.compose.ui.unit.asDpOrPx fun ModifierOrAttrs.toModifier(): Modifier = this?.let { @@ -35,23 +37,41 @@ actual class ModifierOrAttrsScope(modifier: Modifier) { } actual class StyleScope(val modifierOrAttrsScope: ModifierOrAttrsScope<*>) { - actual fun margin(value: NumericSize) = modifierOrAttrsScope.modify { - padding(value.platformValue) + fun modify(block: Modifier.() -> Modifier) = + modifierOrAttrsScope.modify(block) + + actual fun margin(value: LengthOrPercentage) = modify { + padding(value.asDpOrPx().platformValue) } - actual fun height(value: Size) = modifierOrAttrsScope.modify { + actual fun height(value: HeightOrWidth) = modify { when (value) { - FitContent -> this + FitContent -> this //wrapContentHeight() FillMax -> fillMaxHeight() - is Numeric -> height(value.value.platformValue) + is Numeric -> height(value.value.asDpOrPx().platformValue) } } - actual fun width(value: Size) = modifierOrAttrsScope.modify { + actual fun width(value: HeightOrWidth) = modify { + this@modify.fillMaxWidth() when (value) { - FitContent -> this + FitContent -> this //wrapContentWidth() FillMax -> fillMaxHeight() - is Numeric -> width(value.value.platformValue) + is Numeric -> width(value.value.asDpOrPx().platformValue) } } + + + actual fun backgroundColor(color: Color) = modify { + background(color.platformValue) + } + + actual fun border(width: Length, color: Color) = modify { + border(width.asDpOrPx().platformValue, color.platformValue) + } + + actual fun outerBorder(width: Length, color: Color) { + border(width, color) + margin(width) + } } diff --git a/compose-multiplatform-common/src/jvmMain/kotlin/com/huanshankeji/compose/ui/color/ColorJvm.kt b/compose-multiplatform-common/src/jvmMain/kotlin/com/huanshankeji/compose/ui/color/ColorJvm.kt new file mode 100644 index 00000000..3e005362 --- /dev/null +++ b/compose-multiplatform-common/src/jvmMain/kotlin/com/huanshankeji/compose/ui/color/ColorJvm.kt @@ -0,0 +1,16 @@ +package com.huanshankeji.compose.ui.color + +import androidx.compose.ui.graphics.Color as PlatformColor + +typealias PlatformColor = androidx.compose.ui.graphics.Color + +actual class Color(val platformValue: PlatformColor) + +actual fun rgbaColor(red: UByte, green: UByte, blue: UByte, alpha: UByte): Color = + Color(PlatformColor(red.toInt(), green.toInt(), blue.toInt(), alpha.toInt())) + +actual fun rgbaColor(red: UByte, green: UByte, blue: UByte, alpha: Float): Color = + rgbaColor(red, green, blue, alpha.alphaToUByte()) + +actual fun rgbColor(red: UByte, green: UByte, blue: UByte): Color = + Color(PlatformColor(red.toInt(), green.toInt(), blue.toInt())) diff --git a/compose-multiplatform-common/src/jvmMain/kotlin/com/huanshankeji/compose/ui/color/Colors.kt b/compose-multiplatform-common/src/jvmMain/kotlin/com/huanshankeji/compose/ui/color/Colors.kt new file mode 100644 index 00000000..5499b717 --- /dev/null +++ b/compose-multiplatform-common/src/jvmMain/kotlin/com/huanshankeji/compose/ui/color/Colors.kt @@ -0,0 +1,10 @@ +package com.huanshankeji.compose.ui.color + +actual object Colors { + actual val black = Color(PlatformColor.Black) + actual val white = Color(PlatformColor.White) + actual val gray = Color(PlatformColor.Gray) + actual val red = Color(PlatformColor.Red) + actual val green = Color(PlatformColor.Green) + actual val blue = Color(PlatformColor.Blue) +} \ No newline at end of file diff --git a/compose-multiplatform-common/src/jvmMain/kotlin/com/huanshankeji/compose/ui/unit/Sizes.kt b/compose-multiplatform-common/src/jvmMain/kotlin/com/huanshankeji/compose/ui/unit/Sizes.kt index c4bf92e4..c2eec92b 100644 --- a/compose-multiplatform-common/src/jvmMain/kotlin/com/huanshankeji/compose/ui/unit/Sizes.kt +++ b/compose-multiplatform-common/src/jvmMain/kotlin/com/huanshankeji/compose/ui/unit/Sizes.kt @@ -3,8 +3,23 @@ package com.huanshankeji.compose.ui.unit import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp -actual abstract class NumericSize(val platformValue: Dp) -actual class DpOrPx(platformValue: Dp) : NumericSize(platformValue) +actual sealed interface LengthOrPercentage +actual sealed interface Length : LengthOrPercentage + +actual class DpOrPx(val platformValue: Dp) : Length + +fun Length.asDpOrPx() : DpOrPx = + when (this) { + is DpOrPx -> this + // TODO: this else branch is not needed but marked as an error by the IDE plugin + else -> throw AssertionError() + } +fun LengthOrPercentage.asDpOrPx() : DpOrPx = + when (this) { + is DpOrPx -> this + // TODO + else -> throw AssertionError() + } actual val Int.dpOrPx: DpOrPx get() = DpOrPx(this.dp) diff --git a/demo/src/commonMain/kotlin/com/huanshankeji/compose/material/demo/App.kt b/demo/src/commonMain/kotlin/com/huanshankeji/compose/material/demo/App.kt index 383c8a95..59228f80 100644 --- a/demo/src/commonMain/kotlin/com/huanshankeji/compose/material/demo/App.kt +++ b/demo/src/commonMain/kotlin/com/huanshankeji/compose/material/demo/App.kt @@ -7,6 +7,10 @@ import com.huanshankeji.compose.layout.Column import com.huanshankeji.compose.layout.Row import com.huanshankeji.compose.material.* import com.huanshankeji.compose.material.icon.MaterialIcons +import com.huanshankeji.compose.ui.color.Color +import com.huanshankeji.compose.ui.color.Colors +import com.huanshankeji.compose.ui.color.rgbColor +import com.huanshankeji.compose.ui.color.rgbaColor import com.huanshankeji.compose.ui.height import com.huanshankeji.compose.ui.unit.dpOrPx import com.huanshankeji.compose.ui.width @@ -54,7 +58,7 @@ fun App() { }) { ScrollableList({ style { - height(200.dpOrPx) + height(100.dpOrPx) } }) { item { @@ -75,6 +79,31 @@ fun App() { } } } + + Row({ + style { + backgroundColor(rgbColor(0U, 0x80U, 0x00U)) + outerBorder(4.dpOrPx, Colors.blue) + } + }) { + @Composable + fun DemoSquare(color: Color) = + Box({ + style { + // The order of function calls can't be changed! + margin(8.dpOrPx) + backgroundColor(color) + val size = 40.dpOrPx + height(size) + width(size) + } + }) {} + + DemoSquare(Colors.red) + DemoSquare(rgbColor(0xFFU, 0U, 0U)) + DemoSquare(rgbaColor(0xFFU, 0U, 0U, 0x80U)) + DemoSquare(rgbaColor(0xFFU, 0U, 0U, 0.5F)) + } } } } From 8a95126833323069fdb07f45f11e6728073967a1 Mon Sep 17 00:00:00 2001 From: Shreck Ye Date: Mon, 9 Jan 2023 17:02:38 +0800 Subject: [PATCH 31/34] Remove an outdated TODO --- .../src/jsMain/kotlin/com/huanshankeji/compose/ui/unit/Sizes.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/compose-multiplatform-common/src/jsMain/kotlin/com/huanshankeji/compose/ui/unit/Sizes.kt b/compose-multiplatform-common/src/jsMain/kotlin/com/huanshankeji/compose/ui/unit/Sizes.kt index 0b80f4ca..18f353d4 100644 --- a/compose-multiplatform-common/src/jsMain/kotlin/com/huanshankeji/compose/ui/unit/Sizes.kt +++ b/compose-multiplatform-common/src/jsMain/kotlin/com/huanshankeji/compose/ui/unit/Sizes.kt @@ -2,7 +2,6 @@ package com.huanshankeji.compose.ui.unit import org.jetbrains.compose.web.css.* -// TODO: consider adding a platform value type parameter or making it an interface. actual sealed interface LengthOrPercentage { val platformValue: CSSLengthOrPercentageValue From 0ec0764507c7090c6f23714397b8ee700636c0f4 Mon Sep 17 00:00:00 2001 From: Shreck Ye Date: Mon, 9 Jan 2023 22:02:44 +0800 Subject: [PATCH 32/34] Add supported styles in README.md --- README.md | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 402fb212..f1a66bb8 100644 --- a/README.md +++ b/README.md @@ -18,20 +18,22 @@ This project is prototype and there is no documentation yet. Check out [the demo There is no plan to support Apple platforms until there is official support from [Compose Multiplatform](https://github.com/JetBrains/compose-jb). Check out for some experiments and prototypes on supporting iOS with Compose Multiplatform. --> -## Supported components +## Supported features -### Common (Foundation) components +### Components + +#### Common (Foundation) components - `BasicText` - `RawText` -#### Layouts +##### Layouts - `Box` - `Column` (via flexbox on web) - `Row` (via flexbox on web) -### Material components +#### Material components - `Button` - `Card` @@ -40,3 +42,12 @@ There is no plan to support Apple platforms until there is official support from - `ScrollableList`/`LazyColumn` (visually inconsistent for now) - `Text`/`MaterialText` - `TopAppBarScaffold` + +### styles + +- `height` +- `margin` +- `width` +- `backgroundColor` +- `border` +- `outerBorder` From 046b7ff471ab3cc1b86dca974d2a30f642f1b911 Mon Sep 17 00:00:00 2001 From: Shreck Ye Date: Tue, 10 Jan 2023 18:50:50 +0800 Subject: [PATCH 33/34] Implement `roundedCornerOuterBorder`, implement `Percentage` on both platforms, and update the demo --- .../compose/ui/ModifierOrAttrsScope.kt | 11 +++----- .../com/huanshankeji/compose/ui/unit/Sizes.kt | 3 +++ .../compose/ui/ModifierOrAttrsScope.kt | 14 +++++++--- .../com/huanshankeji/compose/ui/unit/Sizes.kt | 5 ++-- .../compose/ui/ModifierOrAttrsScopeJvm.kt | 26 ++++++++++++++----- .../com/huanshankeji/compose/ui/unit/Sizes.kt | 14 ++++++++-- .../huanshankeji/compose/material/demo/App.kt | 3 ++- 7 files changed, 53 insertions(+), 23 deletions(-) diff --git a/compose-multiplatform-common/src/commonMain/kotlin/com/huanshankeji/compose/ui/ModifierOrAttrsScope.kt b/compose-multiplatform-common/src/commonMain/kotlin/com/huanshankeji/compose/ui/ModifierOrAttrsScope.kt index 4de49220..49e45370 100644 --- a/compose-multiplatform-common/src/commonMain/kotlin/com/huanshankeji/compose/ui/ModifierOrAttrsScope.kt +++ b/compose-multiplatform-common/src/commonMain/kotlin/com/huanshankeji/compose/ui/ModifierOrAttrsScope.kt @@ -40,7 +40,7 @@ expect class ModifierOrAttrsScope { * as different orders of CSS properties do in the HTML `style` attribute. */ expect class StyleScope { - fun margin(value: LengthOrPercentage) + fun margin(value: Length) fun height(value: HeightOrWidth) fun width(value: HeightOrWidth) @@ -49,16 +49,11 @@ expect class StyleScope { /** * Currently inconsistent, adds inner border on desktop and Android and outer padding on web. */ - fun border(width: Length, color: Color) + fun platformBorder(width: Length, color: Color) fun outerBorder(width: Length, color: Color) - // TODO - /* - class CornerSize - - fun roundedCornerBorder(width: Length, color: Color, cornerRadius: CornerSize) - */ + fun roundedCornerOuterBorder(width: Length, color: Color, cornerRadius: LengthOrPercentage) } fun StyleScope.height(value: LengthOrPercentage) = diff --git a/compose-multiplatform-common/src/commonMain/kotlin/com/huanshankeji/compose/ui/unit/Sizes.kt b/compose-multiplatform-common/src/commonMain/kotlin/com/huanshankeji/compose/ui/unit/Sizes.kt index b9426f0e..38d8f10c 100644 --- a/compose-multiplatform-common/src/commonMain/kotlin/com/huanshankeji/compose/ui/unit/Sizes.kt +++ b/compose-multiplatform-common/src/commonMain/kotlin/com/huanshankeji/compose/ui/unit/Sizes.kt @@ -3,6 +3,9 @@ package com.huanshankeji.compose.ui.unit // Percentage is only supported on JS. expect sealed interface LengthOrPercentage expect sealed interface Length : LengthOrPercentage +expect class Percentage : LengthOrPercentage + +expect val Int.percent: Percentage expect class DpOrPx : Length diff --git a/compose-multiplatform-common/src/jsMain/kotlin/com/huanshankeji/compose/ui/ModifierOrAttrsScope.kt b/compose-multiplatform-common/src/jsMain/kotlin/com/huanshankeji/compose/ui/ModifierOrAttrsScope.kt index c98f373f..6ebdf13a 100644 --- a/compose-multiplatform-common/src/jsMain/kotlin/com/huanshankeji/compose/ui/ModifierOrAttrsScope.kt +++ b/compose-multiplatform-common/src/jsMain/kotlin/com/huanshankeji/compose/ui/ModifierOrAttrsScope.kt @@ -27,7 +27,10 @@ actual class ModifierOrAttrsScope(val attrsScope: AttrsS } actual class StyleScope(val styleScope: org.jetbrains.compose.web.css.StyleScope) { - actual fun margin(value: LengthOrPercentage) = + actual fun margin(value: Length) = + styleScope.margin(value.platformValue) + + fun margin(value: LengthOrPercentage) = styleScope.margin(value.platformValue) actual fun height(value: HeightOrWidth) = @@ -52,9 +55,14 @@ actual class StyleScope(val styleScope: org.jetbrains.compose.web.css.StyleScope actual fun backgroundColor(color: Color) = styleScope.backgroundColor(color.platformValue) - actual fun border(width: Length, color: Color) = + actual fun platformBorder(width: Length, color: Color) = styleScope.border(width.platformValue, LineStyle.Solid, color.platformValue) actual fun outerBorder(width: Length, color: Color) = - border(width, color) + platformBorder(width, color) + + actual fun roundedCornerOuterBorder(width: Length, color: Color, cornerRadius: LengthOrPercentage) { + outerBorder(width, color) + styleScope.borderRadius(cornerRadius.platformValue) + } } diff --git a/compose-multiplatform-common/src/jsMain/kotlin/com/huanshankeji/compose/ui/unit/Sizes.kt b/compose-multiplatform-common/src/jsMain/kotlin/com/huanshankeji/compose/ui/unit/Sizes.kt index 18f353d4..3fc47e44 100644 --- a/compose-multiplatform-common/src/jsMain/kotlin/com/huanshankeji/compose/ui/unit/Sizes.kt +++ b/compose-multiplatform-common/src/jsMain/kotlin/com/huanshankeji/compose/ui/unit/Sizes.kt @@ -1,6 +1,7 @@ package com.huanshankeji.compose.ui.unit import org.jetbrains.compose.web.css.* +import org.jetbrains.compose.web.css.percent as platformPercent actual sealed interface LengthOrPercentage { val platformValue: CSSLengthOrPercentageValue @@ -14,9 +15,9 @@ actual sealed interface Length : LengthOrPercentage { class Impl(override val platformValue: CSSLengthValue) : Length } -// JS only -class Percentage(override val platformValue: CSSPercentageValue) : LengthOrPercentage +actual class Percentage(override val platformValue: CSSPercentageValue) : LengthOrPercentage +actual val Int.percent get() = Percentage(this.platformPercent) actual class DpOrPx(override val platformValue: CSSpxValue) : Length diff --git a/compose-multiplatform-common/src/jvmMain/kotlin/com/huanshankeji/compose/ui/ModifierOrAttrsScopeJvm.kt b/compose-multiplatform-common/src/jvmMain/kotlin/com/huanshankeji/compose/ui/ModifierOrAttrsScopeJvm.kt index eb12b924..167a6350 100644 --- a/compose-multiplatform-common/src/jvmMain/kotlin/com/huanshankeji/compose/ui/ModifierOrAttrsScopeJvm.kt +++ b/compose-multiplatform-common/src/jvmMain/kotlin/com/huanshankeji/compose/ui/ModifierOrAttrsScopeJvm.kt @@ -3,13 +3,11 @@ package com.huanshankeji.compose.ui import androidx.compose.foundation.background import androidx.compose.foundation.border import androidx.compose.foundation.layout.* +import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.ui.Modifier import com.huanshankeji.compose.ui.color.Color -import com.huanshankeji.compose.ui.unit.HeightOrWidth +import com.huanshankeji.compose.ui.unit.* import com.huanshankeji.compose.ui.unit.HeightOrWidth.* -import com.huanshankeji.compose.ui.unit.Length -import com.huanshankeji.compose.ui.unit.LengthOrPercentage -import com.huanshankeji.compose.ui.unit.asDpOrPx fun ModifierOrAttrs.toModifier(): Modifier = this?.let { @@ -40,7 +38,7 @@ actual class StyleScope(val modifierOrAttrsScope: ModifierOrAttrsScope<*>) { fun modify(block: Modifier.() -> Modifier) = modifierOrAttrsScope.modify(block) - actual fun margin(value: LengthOrPercentage) = modify { + actual fun margin(value: Length) = modify { padding(value.asDpOrPx().platformValue) } @@ -66,12 +64,26 @@ actual class StyleScope(val modifierOrAttrsScope: ModifierOrAttrsScope<*>) { background(color.platformValue) } - actual fun border(width: Length, color: Color) = modify { + actual fun platformBorder(width: Length, color: Color) = modify { border(width.asDpOrPx().platformValue, color.platformValue) } actual fun outerBorder(width: Length, color: Color) { - border(width, color) + platformBorder(width, color) + margin(width) + } + + actual fun roundedCornerOuterBorder(width: Length, color: Color, cornerRadius: LengthOrPercentage) { + modify { + border( + width.asDpOrPx().platformValue, color.platformValue, when (cornerRadius) { + is DpOrPx -> RoundedCornerShape(cornerRadius.platformValue) + is Percentage -> RoundedCornerShape(cornerRadius.value) + // TODO + else -> throw AssertionError() + } + ) + } margin(width) } } diff --git a/compose-multiplatform-common/src/jvmMain/kotlin/com/huanshankeji/compose/ui/unit/Sizes.kt b/compose-multiplatform-common/src/jvmMain/kotlin/com/huanshankeji/compose/ui/unit/Sizes.kt index c2eec92b..cdb7a950 100644 --- a/compose-multiplatform-common/src/jvmMain/kotlin/com/huanshankeji/compose/ui/unit/Sizes.kt +++ b/compose-multiplatform-common/src/jvmMain/kotlin/com/huanshankeji/compose/ui/unit/Sizes.kt @@ -5,16 +5,26 @@ import androidx.compose.ui.unit.dp actual sealed interface LengthOrPercentage actual sealed interface Length : LengthOrPercentage +actual typealias Percentage = PercentageImpl + +class PercentageImpl(val value: Int) : LengthOrPercentage { + init { + require(value in 0..100) + } +} + +actual val Int.percent get() = Percentage(this) actual class DpOrPx(val platformValue: Dp) : Length -fun Length.asDpOrPx() : DpOrPx = +fun Length.asDpOrPx(): DpOrPx = when (this) { is DpOrPx -> this // TODO: this else branch is not needed but marked as an error by the IDE plugin else -> throw AssertionError() } -fun LengthOrPercentage.asDpOrPx() : DpOrPx = + +fun LengthOrPercentage.asDpOrPx(): DpOrPx = when (this) { is DpOrPx -> this // TODO diff --git a/demo/src/commonMain/kotlin/com/huanshankeji/compose/material/demo/App.kt b/demo/src/commonMain/kotlin/com/huanshankeji/compose/material/demo/App.kt index 59228f80..26f8fea8 100644 --- a/demo/src/commonMain/kotlin/com/huanshankeji/compose/material/demo/App.kt +++ b/demo/src/commonMain/kotlin/com/huanshankeji/compose/material/demo/App.kt @@ -82,8 +82,9 @@ fun App() { Row({ style { + // The order of function calls can't be changed! + roundedCornerOuterBorder(4.dpOrPx, Colors.blue, 16.dpOrPx) backgroundColor(rgbColor(0U, 0x80U, 0x00U)) - outerBorder(4.dpOrPx, Colors.blue) } }) { @Composable From d8c7ed2ce9269c90e741f9874cf596568fbd4258 Mon Sep 17 00:00:00 2001 From: Shreck Ye Date: Tue, 10 Jan 2023 20:52:54 +0800 Subject: [PATCH 34/34] Use compose-web-material v0.2.0 --- buildSrc/src/main/kotlin/VersionsAndDependencies.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buildSrc/src/main/kotlin/VersionsAndDependencies.kt b/buildSrc/src/main/kotlin/VersionsAndDependencies.kt index dc5b5452..dd079241 100644 --- a/buildSrc/src/main/kotlin/VersionsAndDependencies.kt +++ b/buildSrc/src/main/kotlin/VersionsAndDependencies.kt @@ -1,3 +1,3 @@ object DependencyVersions { - val huanshankejiComposeWeb = "0.2.0-SNAPSHOT" // TODO: don't use a snapshot version in a main branch + val huanshankejiComposeWeb = "0.2.0" }