Skip to content

Commit

Permalink
Merge branch 'main' into release
Browse files Browse the repository at this point in the history
v0.3.0 release
  • Loading branch information
ShreckYe committed May 9, 2024
2 parents 1d1aa70 + 6227939 commit 066bcf0
Show file tree
Hide file tree
Showing 48 changed files with 1,632 additions and 75 deletions.
97 changes: 74 additions & 23 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,42 +1,93 @@
# Compose for Web (now Compose HTML) Material
# Compose HTML Material

[![Maven Central](https://img.shields.io/maven-central/v/com.huanshankeji/compose-web-material)](https://search.maven.org/artifact/com.huanshankeji/compose-web-material)
[![Gradle Plugin Portal](https://img.shields.io/gradle-plugin-portal/v/com.huanshankeji.compose-web-material-conventions)](https://plugins.gradle.org/plugin/com.huanshankeji.compose-web-material-conventions)
[![Maven Central](https://img.shields.io/maven-central/v/com.huanshankeji/compose-html-material3)](https://search.maven.org/artifact/com.huanshankeji/compose-html-material3)

Some Material components for Compose for Web, based on [Material Web (with Web Components) (or material-web, or `mwc`)](https://github.com/material-components/material-web) (preferred) and [Material Components for the web (or material-components-web, or `mdc`)](https://github.com/material-components/material-components-web) (fallback)
Material 3 wrapper components for Compose HTML based on [Material Web](https://github.com/material-components/material-web)

~~This project is in prototype and the components are not complete. More components will be added. It will probably go through huge refactors and API changes, too.~~
For unified multiplatform APIs which are more akin to those in `androidx.compose`, check out [Compose Multiplatform Material](https://github.com/huanshankeji/compose-multiplatform-material).

**This project is not currently under active development. Here is a list of reasons and alternatives:**
For Material 2 support, you are recommended to check out [KMDC](https://github.com/mpetuska/kmdc) instead. For information on our obsolete work on legacy Material 2 components, check out [the legacy README](/legacy/README.md).

1. The [material-web](https://github.com/material-components/material-web) team is working on Material You (Material Design 3) support and [the Material 2 branch (`mwc`)](https://github.com/material-components/material-web/tree/mwc) is no longer under active development. Existing Compose wrappers of their Material 2 components are still kept in [the `:compose-web-material` subproject](compose-web-material) but not updated.
1. [KMDC](https://github.com/mpetuska/kmdc) wrapping around [material-components-web (`mdc`)](https://github.com/material-components/material-components-web) provides a much more complete set of Material Design components for Compose for Web.
1. We are currently focusing more on [compose-multiplatform-material](https://github.com/huanshankeji/compose-multiplatform-material) to provide multiplatform Compose Material wrappers, whose web portion depends on KMDC and [the `:compose-web-common` subproject](compose-web-common), which may be occasionally updated for the dependent project.
## Supported components

## Instructions on how to use
Not all components of Material Web are supported yet. Also, not all Material Design components are supported by Material Web yet (see [their roadmap](https://github.com/material-components/material-web/blob/main/docs/roadmap.md)).

Some configurations are needed to use this library due to the immaturities of this project and Kotlin/JS.
Here is a list of supported compoent APIs:

### Add the dependency
- `MdElevatedButton`, `MdFilledButton`, `MdFilledTonalButton`, `MdOutlinedButton`, `MdTextButton`
- `MdCheckbox`
- `MdFab`, `MdBrandedFab`
- `MdIcon`
- `MdIconButton`, `MdFilledIconButton`, `MdFilledTonalIconButton`, `MdOutlinedIconButton`
- `MdList`, `MdListItem`
- `MdSwitch`, `LabelWithMdSwitch`
- `MdFilledTextField`, `MdOutlinedTextField`

```kotlin
implementation("com.huanshankeji:compose-web-material:$version")
```
### "labs" components

### In code
Here is a list of supported component APIs in the [Material Web "labs" directory](https://github.com/material-components/material-web/tree/main/labs), which "contains experimental features that are not recommended for production" as they state:

Call `mwcRequires()` in your `main` function before calling any component Composable functions.
- `MdElevatedCard`, `MdOutlinedCard`
- `MdNavigationBar`
- `MdNavigationTab`

### Kotlin/JS Webpack configuration
You should opt-in to `@MaterialWebLabsApi` to use them.

If you use this library in an app project with Webpack [which Kotlin/JS currently uses](https://kotlinlang.org/docs/js-project-setup.html), you might want to configure it as recommended by Material Web and Material Components for the web. Some instructions on how to do this simply are as below.
## Brief Instructions

### Add the dependency

This plugin helps add the dependency to this project (if you do this you can skip the "Add the dependency" step above) and the `devNpm` dependencies:
With Gradle:

```kotlin
plugins {
id("com.huanshankeji.compose-web-material-conventions") version someVersion
kotlin {
sourceSets {
jsMain {
dependencies {
// ...
implementation("com.huanshankeji:compose-html-material3:$version")
}
}
}
}
```

However, the plugin doesn't [make further adjustments to the webpack configuration](https://kotlinlang.org/docs/js-project-setup.html#webpack-configuration-file), so you also need to refer to [the demo further adjustments](demo/webpack.config.d/further_adjustments.js) and [the demo HTML page](demo/html/demo.html) to add your own. Just copy and possibly adapt them as you like.
### Material Symbols & Icons

The Material 3 module uses [Material Symbols & Icons](https://fonts.google.com/icons), but doesn't depend on the stylesheet directly. For Material Icons to work properly, you may need to configure your project following the quick instructions below or [the developer guide](https://developers.google.com/fonts/docs/material_symbols).

#### Quick instructions

In short, there are 3 ways to add the Material Symbols & Icons dependency:

1. Add the stylesheet hosted by Google directly in your HTML file `head`:

```html
<link href="https://fonts.googleapis.com/icon?family=Material+Symbols+Outlined" rel="stylesheet">
```

1. Use [Marella's self-hosted Material Symbols](https://www.npmjs.com/package/material-symbols).

First add the dependency in your build script:

```kotlin
implementation(npm("material-symbols", "0.17.4"))
```

And then import the icons in your program. For example you can use CommonJS `require`:

```kotlin
external fun require(module: String): dynamic
fun main() {
require("material-symbols/outlined.css")
renderComposableInBody { App() }
}
```

If you are familiar with web development and Kotlin/JS, you can depend on the stylesheet in any way that works and you prefer. For example, you can use `@JsModule` corresponding to the UMD import, or configure it as a Webpack entry point. See the following docs fore more details:
1. [JavaScript modules | Kotlin Documentation](https://kotlinlang.org/docs/js-modules.html)
1. [the "webpack configuration file" section in Set up a Kotlin/JS project | Kotlin Documentation](https://kotlinlang.org/docs/js-project-setup.html#webpack-configuration-file)
1. [Code Splitting | webpack](https://webpack.js.org/guides/code-splitting/)
1. [Advanced entry | webpack](https://webpack.js.org/guides/entry-advanced/)

1. [Download and self-host the latest font](https://developers.google.com/fonts/docs/material_symbols#self-hosting_the_font).
2 changes: 1 addition & 1 deletion buildSrc/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ val huanshankejiGradlePluginsVersion = "0.5.1"

dependencies {
implementation(kotlin("gradle-plugin", "1.9.23"))
implementation("org.jetbrains.compose:compose-gradle-plugin:1.6.1")
implementation("org.jetbrains.compose:compose-gradle-plugin:1.6.2")
implementation("com.huanshankeji:kotlin-common-gradle-plugins:$huanshankejiGradlePluginsVersion")
implementation("com.huanshankeji.team:gradle-plugins:$huanshankejiGradlePluginsVersion")
implementation("com.huanshankeji:common-gradle-dependencies:0.7.1-20240314")
Expand Down
8 changes: 7 additions & 1 deletion buildSrc/src/main/kotlin/VersionsAndDependencies.kt
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
import com.huanshankeji.CommonDependencies

const val projectVersion = "0.2.2"
const val projectVersion = "0.3.0"

object DependencyVersions {
val kobweb = "0.17.3"
val materialWeb = "1.4.1"


// legacy versions that don't need to be updated

val webcomponents = "2.6.0"
val mwc = "0.25.3"

Expand Down
7 changes: 1 addition & 6 deletions buildSrc/src/main/kotlin/lib-conventions.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,9 +1,3 @@
import com.huanshankeji.team.`Shreck Ye`
import com.huanshankeji.team.pomForTeamDefaultOpenSource
import org.gradle.api.publish.maven.MavenPublication
import org.gradle.api.tasks.bundling.Jar
import org.gradle.kotlin.dsl.*

plugins {
id("com.huanshankeji.kotlin-multiplatform-js-browser-conventions")
id("org.jetbrains.compose")
Expand All @@ -12,6 +6,7 @@ plugins {

repositories {
maven("https://maven.pkg.jetbrains.space/public/p/compose/dev")
maven("https://us-central1-maven.pkg.dev/varabyte-repos/public") // for Kobweb
}

group = "com.huanshankeji"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ kotlin {
dependencies {
implementation(compose.html.core)
implementation(compose.runtime)
implementation(commonDependencies.kotlinx.coroutines.core())
api("com.varabyte.kobweb:compose-html-ext:${DependencyVersions.kobweb}")
//implementation(commonDependencies.kotlinx.coroutines.core())
}
}
}
Expand All @@ -20,8 +21,8 @@ kotlin {
publishing.publications.withType<MavenPublication> {
pomForTeamDefaultOpenSource(
project,
"Huanshankeji Compose for Web common",
"Huanshankeji's common code for Compose for Web"
"Huanshankeji Compose HTML common",
"Huanshankeji's common code for Compose HTML"
) {
`Shreck Ye`()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,13 @@ fun Flexbox(
}
} + attrs, content)

@Composable
@PreferringKobwebComposeLayoutApi
@Deprecated(WITH_STYLES_DEPRECATED_MESSAGE)
@Composable
fun FlexboxS(styles: Styles? = null, content: ContentBuilder<HTMLDivElement>) =
Flexbox(styles.wrapInAttrs(), content)

@PreferringKobwebComposeLayoutApi
@Composable
fun Column(
attrs: AttrBuilderContext<HTMLDivElement>? = null,
Expand All @@ -48,11 +50,13 @@ fun Column(
}
} + attrs, content)

@Composable
@PreferringKobwebComposeLayoutApi
@Deprecated(WITH_STYLES_DEPRECATED_MESSAGE)
@Composable
fun ColumnS(styles: Styles? = null, fitContent: Boolean = true, content: ContentBuilder<HTMLDivElement>) =
Column(styles.wrapInAttrs(), fitContent, content)

@PreferringKobwebComposeLayoutApi
@Composable
fun ColumnWithSpaceBetween(
attrs: AttrBuilderContext<HTMLDivElement>? = null,
Expand All @@ -66,6 +70,7 @@ fun ColumnWithSpaceBetween(
} + attrs, fitContent, content)


@PreferringKobwebComposeLayoutApi
@Composable
fun Row(
attrs: AttrBuilderContext<HTMLDivElement>? = null,
Expand All @@ -77,14 +82,16 @@ fun Row(
}
} + attrs, content)

@Composable
@PreferringKobwebComposeLayoutApi
@Deprecated(WITH_STYLES_DEPRECATED_MESSAGE)
@Composable
fun RowS(
styles: Styles? = null,
content: ContentBuilder<HTMLDivElement>
) =
Row(styles.wrapInAttrs(), content)

@PreferringKobwebComposeLayoutApi
@Composable
fun RowWithSpaceBetween(
attrs: AttrBuilderContext<HTMLDivElement>? = null,
Expand All @@ -96,6 +103,7 @@ fun RowWithSpaceBetween(
}
} + attrs, content)

@PreferringKobwebComposeLayoutApi
@Composable
fun ColumnWithGaps(
attrs: AttrBuilderContext<HTMLDivElement>? = null,
Expand All @@ -109,6 +117,7 @@ fun ColumnWithGaps(
}
} + attrs, fitContent, content)

@PreferringKobwebComposeLayoutApi
@Composable
fun RowWithGaps(
attrs: AttrBuilderContext<HTMLDivElement>? = null,
Expand Down Expand Up @@ -158,6 +167,8 @@ fun FrGrid(
}
}, content)

@PreferringKobwebComposeLayoutApi
@Deprecated("This API is not implemented yet.")
@Composable
fun Spacer(numPxs: Int) =
TODO() as Unit
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.huanshankeji.compose.web

@RequiresOptIn(
"You are recommend to use the similar layout APIs in Kobweb Compose. See \"https://github.com/varabyte/kobweb/tree/main/frontend/kobweb-compose/src/jsMain/kotlin/com/varabyte/kobweb/compose/foundation/layout\".",
RequiresOptIn.Level.WARNING
)
@Retention(AnnotationRetention.BINARY)
@Target(AnnotationTarget.FUNCTION)
annotation class PreferringKobwebComposeLayoutApi
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.huanshankeji.compose.web.attributes

// consider moving to a "web-common" or "html-common" module

fun Boolean.isTrueOrNull(): Boolean? =
if (this) true else null

fun Boolean.isFalseOrNull(): Boolean? =
if (this) null else false

fun Boolean.toOnOrOff(): String =
if (this) "on" else "off"
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package com.huanshankeji.compose.web.attributes

import org.jetbrains.compose.web.attributes.AttrsScope

/**
* Adds an attribute that is made present by its key aka [attr].
* @see AttrsScope.attr
*/
fun AttrsScope<*>.attr(attr: String, value: Boolean = true) =
attr(attr, value.toString())

/**
* [Int] attributes are used in Compose HTML. See [org.jetbrains.compose.web.attributes.maxLength] for example.
*/
fun AttrsScope<*>.attr(attr: String, value: Int) =
attr(attr, value.toString())

/**
* Adds an attribute that has an explicit [Boolean] value unlike [attr].
*/
fun AttrsScope<*>.booleanAttr(attr: String, value: Boolean) =
attr(attr, value.toString())


fun AttrsScope<*>.attrIfNotNull(attr: String, value: String?) {
value?.let { attr(attr, it) }
}

fun AttrsScope<*>.attrIfNotNull(attr: String, value: Boolean?) {
value?.let { attr(attr, it) }
}

fun AttrsScope<*>.attrIfNotNull(attr: String, value: Int?) {
value?.let { attr(attr, it) }
}


// https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/slot
fun AttrsScope<*>.slot(value: String) =
attr("slot", value)


enum class AutoCapitalize(val strValue: String, val alternativeStrValue: String? = null) {
None("none", "off"), Sentences("sentences", "on"), Words("words"), Characters("characters");

companion object {
val valueSet = entries.asSequence().map { it.strValue }.toSet()
}
}

// This is actually a global attribute
// https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/autocapitalize
fun AttrsScope<*>.autoCapitalize(value: String) =
attr("autocapitalize", value)

fun AttrsScope<*>.autoCapitalize(value: AutoCapitalize) =
autoCapitalize(value.strValue)


// Safari only
// https://developer.mozilla.org/en-US/docs/Web/HTML/Element/Input#attr-autocorrect
fun AttrsScope<*>.autocorrect(value: String) =
attr("autocorrect", value)

fun AttrsScope<*>.autocorrect(onOrOff: Boolean) =
attr("autocorrect", onOrOff.toOnOrOff())


enum class EnterKeyHint(val strValue: String) {
Enter("enter"), Done("done"), Go("go"), Next("next"), Previous("previous"), Search("search"), Send("send");

companion object {
val valueSet = entries.map { it.strValue }.toSet()
}
}

// https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/enterkeyhint
fun AttrsScope<*>.enterKeyHint(value: String) =
attr("enterkeyhint", value)

fun AttrsScope<*>.enterKeyHint(value: EnterKeyHint) =
enterKeyHint(value.strValue)
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.huanshankeji.compose.web.attributes

import org.jetbrains.compose.web.attributes.AttrsScope

typealias Attrs<Element> = AttrsScope<Element>.() -> Unit
Loading

0 comments on commit 066bcf0

Please sign in to comment.