From 2c6904545f5f4c38c88e6eb61f5afd8c37709244 Mon Sep 17 00:00:00 2001 From: Shreck Ye Date: Sun, 14 Apr 2024 17:44:03 +0800 Subject: [PATCH 01/34] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index de5dcb0..cdc2c74 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# 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) From 80512f25f9f6d4dbc35626de0c412c04cb3e2eed Mon Sep 17 00:00:00 2001 From: Shreck Ye Date: Sun, 14 Apr 2024 17:44:37 +0800 Subject: [PATCH 02/34] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index cdc2c74..b7a3ca9 100644 --- a/README.md +++ b/README.md @@ -3,14 +3,14 @@ [![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) -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) +Some Material components for Compose HTML, 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) ~~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.~~ **This project is not currently under active development. Here is a list of reasons and alternatives:** 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. [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 HTML. 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. ## Instructions on how to use From 23ef943776676809ac2d9f46af983d82df66b6b6 Mon Sep 17 00:00:00 2001 From: Shreck Ye Date: Mon, 15 Apr 2024 02:21:30 +0800 Subject: [PATCH 03/34] Rename occurrences of "Compose for Web" and "compose-web" into "Compose HTML" and "compose-html" and move related code --- README.md | 18 +++++++++++++----- .../src/main/kotlin/VersionsAndDependencies.kt | 2 +- .../build.gradle.kts | 4 ++-- .../com/huanshankeji/compose/web/Layouts.kt | 0 .../huanshankeji/compose/web/LoadingState.kt | 0 .../com/huanshankeji/compose/web/Types.kt | 0 .../web/attributes/AttrBuilderContext.kt | 0 .../compose/web/attributes/AttrsScope.kt | 0 .../com/huanshankeji/compose/web/css/CSS.kt | 0 .../huanshankeji/compose/web/css/StyleScope.kt | 0 .../com/huanshankeji/compose/web/css/Styles.kt | 0 .../compose/web/dom/ElementScope.kt | 0 .../build.gradle.kts | 6 +++--- .../compose/web/material/Components.kt | 0 .../compose/web/material/Layouts.kt | 0 .../compose/web/material/MwcRequires.kt | 0 .../compose/web/material/Styles.kt | 0 .../kotlin/com/huanshankeji/material/Colors.kt | 0 gradle-plugins/build.gradle.kts | 10 +++++----- ...mpose-html-material-conventions.gradle.kts} | 2 +- settings.gradle.kts | 6 +++--- 21 files changed, 28 insertions(+), 20 deletions(-) rename {compose-web-common => compose-html-common}/build.gradle.kts (84%) rename {compose-web-common => compose-html-common}/src/jsMain/kotlin/com/huanshankeji/compose/web/Layouts.kt (100%) rename {compose-web-common => compose-html-common}/src/jsMain/kotlin/com/huanshankeji/compose/web/LoadingState.kt (100%) rename {compose-web-common => compose-html-common}/src/jsMain/kotlin/com/huanshankeji/compose/web/Types.kt (100%) rename {compose-web-common => compose-html-common}/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/AttrBuilderContext.kt (100%) rename {compose-web-common => compose-html-common}/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/AttrsScope.kt (100%) rename {compose-web-common => compose-html-common}/src/jsMain/kotlin/com/huanshankeji/compose/web/css/CSS.kt (100%) rename {compose-web-common => compose-html-common}/src/jsMain/kotlin/com/huanshankeji/compose/web/css/StyleScope.kt (100%) rename {compose-web-common => compose-html-common}/src/jsMain/kotlin/com/huanshankeji/compose/web/css/Styles.kt (100%) rename {compose-web-common => compose-html-common}/src/jsMain/kotlin/com/huanshankeji/compose/web/dom/ElementScope.kt (100%) rename {compose-web-material => compose-html-material}/build.gradle.kts (89%) rename {compose-web-material => compose-html-material}/src/jsMain/kotlin/com/huanshankeji/compose/web/material/Components.kt (100%) rename {compose-web-material => compose-html-material}/src/jsMain/kotlin/com/huanshankeji/compose/web/material/Layouts.kt (100%) rename {compose-web-material => compose-html-material}/src/jsMain/kotlin/com/huanshankeji/compose/web/material/MwcRequires.kt (100%) rename {compose-web-material => compose-html-material}/src/jsMain/kotlin/com/huanshankeji/compose/web/material/Styles.kt (100%) rename {compose-web-material => compose-html-material}/src/jsMain/kotlin/com/huanshankeji/material/Colors.kt (100%) rename gradle-plugins/src/main/kotlin/com/huanshankeji/{compose-web-material-conventions.gradle.kts => compose-html-material-conventions.gradle.kts} (88%) diff --git a/README.md b/README.md index b7a3ca9..3276a17 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # 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-material)](https://search.maven.org/artifact/com.huanshankeji/compose-html-material) +[![Gradle Plugin Portal](https://img.shields.io/gradle-plugin-portal/v/com.huanshankeji.compose-html-material-conventions)](https://plugins.gradle.org/plugin/com.huanshankeji.compose-html-material-conventions) Some Material components for Compose HTML, 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) @@ -9,9 +9,9 @@ Some Material components for Compose HTML, based on [Material Web (with Web Comp **This project is not currently under active development. Here is a list of reasons and alternatives:** -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. 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-html-material` subproject](compose-html-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 HTML. -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. +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-html-common` subproject](compose-html-common), which may be occasionally updated for the dependent project. ## Instructions on how to use @@ -19,10 +19,18 @@ Some configurations are needed to use this library due to the immaturities of th ### Add the dependency +Prior to v0.3.0: + ```kotlin implementation("com.huanshankeji:compose-web-material:$version") ``` +Since v0.3.0: + +```kotlin +implementation("com.huanshankeji:compose-html-material:$version") +``` + ### In code Call `mwcRequires()` in your `main` function before calling any component Composable functions. @@ -31,7 +39,7 @@ Call `mwcRequires()` in your `main` function before calling any component Compos 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. -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: +If you use a version prior to v0.3.0, 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: ```kotlin plugins { diff --git a/buildSrc/src/main/kotlin/VersionsAndDependencies.kt b/buildSrc/src/main/kotlin/VersionsAndDependencies.kt index 558160c..d8ed8e1 100644 --- a/buildSrc/src/main/kotlin/VersionsAndDependencies.kt +++ b/buildSrc/src/main/kotlin/VersionsAndDependencies.kt @@ -1,6 +1,6 @@ import com.huanshankeji.CommonDependencies -const val projectVersion = "0.2.2-SNAPSHOT" +const val projectVersion = "0.3.0-SNAPSHOT" object DependencyVersions { val webcomponents = "2.6.0" diff --git a/compose-web-common/build.gradle.kts b/compose-html-common/build.gradle.kts similarity index 84% rename from compose-web-common/build.gradle.kts rename to compose-html-common/build.gradle.kts index f570584..be6d98f 100644 --- a/compose-web-common/build.gradle.kts +++ b/compose-html-common/build.gradle.kts @@ -20,8 +20,8 @@ kotlin { publishing.publications.withType { 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`() } diff --git a/compose-web-common/src/jsMain/kotlin/com/huanshankeji/compose/web/Layouts.kt b/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/Layouts.kt similarity index 100% rename from compose-web-common/src/jsMain/kotlin/com/huanshankeji/compose/web/Layouts.kt rename to compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/Layouts.kt diff --git a/compose-web-common/src/jsMain/kotlin/com/huanshankeji/compose/web/LoadingState.kt b/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/LoadingState.kt similarity index 100% rename from compose-web-common/src/jsMain/kotlin/com/huanshankeji/compose/web/LoadingState.kt rename to compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/LoadingState.kt diff --git a/compose-web-common/src/jsMain/kotlin/com/huanshankeji/compose/web/Types.kt b/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/Types.kt similarity index 100% rename from compose-web-common/src/jsMain/kotlin/com/huanshankeji/compose/web/Types.kt rename to compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/Types.kt diff --git a/compose-web-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/AttrBuilderContext.kt b/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/AttrBuilderContext.kt similarity index 100% rename from compose-web-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/AttrBuilderContext.kt rename to compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/AttrBuilderContext.kt diff --git a/compose-web-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/AttrsScope.kt b/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/AttrsScope.kt similarity index 100% rename from compose-web-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/AttrsScope.kt rename to compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/AttrsScope.kt diff --git a/compose-web-common/src/jsMain/kotlin/com/huanshankeji/compose/web/css/CSS.kt b/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/css/CSS.kt similarity index 100% rename from compose-web-common/src/jsMain/kotlin/com/huanshankeji/compose/web/css/CSS.kt rename to compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/css/CSS.kt diff --git a/compose-web-common/src/jsMain/kotlin/com/huanshankeji/compose/web/css/StyleScope.kt b/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/css/StyleScope.kt similarity index 100% rename from compose-web-common/src/jsMain/kotlin/com/huanshankeji/compose/web/css/StyleScope.kt rename to compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/css/StyleScope.kt diff --git a/compose-web-common/src/jsMain/kotlin/com/huanshankeji/compose/web/css/Styles.kt b/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/css/Styles.kt similarity index 100% rename from compose-web-common/src/jsMain/kotlin/com/huanshankeji/compose/web/css/Styles.kt rename to compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/css/Styles.kt diff --git a/compose-web-common/src/jsMain/kotlin/com/huanshankeji/compose/web/dom/ElementScope.kt b/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/dom/ElementScope.kt similarity index 100% rename from compose-web-common/src/jsMain/kotlin/com/huanshankeji/compose/web/dom/ElementScope.kt rename to compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/dom/ElementScope.kt diff --git a/compose-web-material/build.gradle.kts b/compose-html-material/build.gradle.kts similarity index 89% rename from compose-web-material/build.gradle.kts rename to compose-html-material/build.gradle.kts index d7f2fcc..570c7be 100644 --- a/compose-web-material/build.gradle.kts +++ b/compose-html-material/build.gradle.kts @@ -11,7 +11,7 @@ kotlin { dependencies { implementation(compose.html.core) implementation(compose.runtime) - implementation(project(":compose-web-common")) + implementation(project(":compose-html-common")) implementation(npm("@webcomponents/webcomponentsjs", DependencyVersions.webcomponents)) @@ -43,8 +43,8 @@ kotlin { publishing.publications.withType { pomForTeamDefaultOpenSource( project, - "Compose for Web Material", - "Some Material components for Compose for Web" + "Compose HTML Material", + "Some Material components for Compose HTML" ) { `Shreck Ye`() } diff --git a/compose-web-material/src/jsMain/kotlin/com/huanshankeji/compose/web/material/Components.kt b/compose-html-material/src/jsMain/kotlin/com/huanshankeji/compose/web/material/Components.kt similarity index 100% rename from compose-web-material/src/jsMain/kotlin/com/huanshankeji/compose/web/material/Components.kt rename to compose-html-material/src/jsMain/kotlin/com/huanshankeji/compose/web/material/Components.kt diff --git a/compose-web-material/src/jsMain/kotlin/com/huanshankeji/compose/web/material/Layouts.kt b/compose-html-material/src/jsMain/kotlin/com/huanshankeji/compose/web/material/Layouts.kt similarity index 100% rename from compose-web-material/src/jsMain/kotlin/com/huanshankeji/compose/web/material/Layouts.kt rename to compose-html-material/src/jsMain/kotlin/com/huanshankeji/compose/web/material/Layouts.kt diff --git a/compose-web-material/src/jsMain/kotlin/com/huanshankeji/compose/web/material/MwcRequires.kt b/compose-html-material/src/jsMain/kotlin/com/huanshankeji/compose/web/material/MwcRequires.kt similarity index 100% rename from compose-web-material/src/jsMain/kotlin/com/huanshankeji/compose/web/material/MwcRequires.kt rename to compose-html-material/src/jsMain/kotlin/com/huanshankeji/compose/web/material/MwcRequires.kt diff --git a/compose-web-material/src/jsMain/kotlin/com/huanshankeji/compose/web/material/Styles.kt b/compose-html-material/src/jsMain/kotlin/com/huanshankeji/compose/web/material/Styles.kt similarity index 100% rename from compose-web-material/src/jsMain/kotlin/com/huanshankeji/compose/web/material/Styles.kt rename to compose-html-material/src/jsMain/kotlin/com/huanshankeji/compose/web/material/Styles.kt diff --git a/compose-web-material/src/jsMain/kotlin/com/huanshankeji/material/Colors.kt b/compose-html-material/src/jsMain/kotlin/com/huanshankeji/material/Colors.kt similarity index 100% rename from compose-web-material/src/jsMain/kotlin/com/huanshankeji/material/Colors.kt rename to compose-html-material/src/jsMain/kotlin/com/huanshankeji/material/Colors.kt diff --git a/gradle-plugins/build.gradle.kts b/gradle-plugins/build.gradle.kts index 1ac43eb..db060c0 100644 --- a/gradle-plugins/build.gradle.kts +++ b/gradle-plugins/build.gradle.kts @@ -31,15 +31,15 @@ group = "com.huanshankeji" version = projectVersion gradlePlugin { - website.set("https://github.com/huanshankeji/compose-web-material") + website.set("https://github.com/huanshankeji/compose-html-material") vcsUrl.set("${website.get()}.git") plugins { - getByName("com.huanshankeji.compose-web-material-conventions") { - displayName = "Compose for Web Material conventions" + getByName("com.huanshankeji.compose-html-material-conventions") { + displayName = "Compose HTML Material conventions" description = - "This plugin adds the needed Maven dependencies and npm devDependencies (mainly for Webpack) for a Compose for Web project with Material components." - tags.set(listOf("kotlin", "kotlin-js", "compose-multiplatform", "compose-web")) + "This plugin adds the needed Maven dependencies and npm devDependencies (mainly for Webpack) for a Compose HTML project with Material components." + tags.set(listOf("kotlin", "kotlin-js", "compose-multiplatform", "compose-html")) } } } diff --git a/gradle-plugins/src/main/kotlin/com/huanshankeji/compose-web-material-conventions.gradle.kts b/gradle-plugins/src/main/kotlin/com/huanshankeji/compose-html-material-conventions.gradle.kts similarity index 88% rename from gradle-plugins/src/main/kotlin/com/huanshankeji/compose-web-material-conventions.gradle.kts rename to gradle-plugins/src/main/kotlin/com/huanshankeji/compose-html-material-conventions.gradle.kts index fc2af9f..6626d14 100644 --- a/gradle-plugins/src/main/kotlin/com/huanshankeji/compose-web-material-conventions.gradle.kts +++ b/gradle-plugins/src/main/kotlin/com/huanshankeji/compose-html-material-conventions.gradle.kts @@ -10,7 +10,7 @@ kotlin { sourceSets { val jsMain by getting { dependencies { - implementation("com.huanshankeji:compose-web-material:$projectVersion") + implementation("com.huanshankeji:compose-html-material:$projectVersion") implementation(devNpm("css-loader", NpmDevDependencyVersions.cssLoader)) implementation(devNpm("extract-loader", NpmDevDependencyVersions.extractLoader)) diff --git a/settings.gradle.kts b/settings.gradle.kts index 897a4c8..07ef072 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,6 +1,6 @@ -rootProject.name = "compose-web-material" +rootProject.name = "compose-html-material" -include("compose-web-common") -include(rootProject.name) +include("compose-html-common") +include("compose-html-material") include("gradle-plugins") project(":gradle-plugins").name = rootProject.name + "-gradle-plugins" From db22ff74b8a542459c5f6fbd24b89218f19e4093 Mon Sep 17 00:00:00 2001 From: Shreck Ye Date: Mon, 15 Apr 2024 02:59:21 +0800 Subject: [PATCH 04/34] Add the empty `compose-html-material3` module and update some more text in both README.md and the Maven POM --- README.md | 6 +++--- compose-html-material/build.gradle.kts | 4 ++-- settings.gradle.kts | 1 + 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 3276a17..c845e75 100644 --- a/README.md +++ b/README.md @@ -3,13 +3,13 @@ [![Maven Central](https://img.shields.io/maven-central/v/com.huanshankeji/compose-html-material)](https://search.maven.org/artifact/com.huanshankeji/compose-html-material) [![Gradle Plugin Portal](https://img.shields.io/gradle-plugin-portal/v/com.huanshankeji.compose-html-material-conventions)](https://plugins.gradle.org/plugin/com.huanshankeji.compose-html-material-conventions) -Some Material components for Compose HTML, 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) +Some Material components for Compose HTML, with legacy Material 2 wrapper components based on [the obsolete `mwc` branch of Material Web](https://github.com/material-components/material-web/tree/mwc) (preferred) and [Material Components for the web (or material-components-web, or `mdc`)](https://github.com/material-components/material-components-web) (fallback), and Material 3 wrapper components 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.~~ -**This project is not currently under active development. Here is a list of reasons and alternatives:** +**The Material 2 portion of this project is not currently under active development. Here is a list of reasons and alternatives:** -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-html-material` subproject](compose-html-material) but not updated. +1. The [material-web](https://github.com/material-components/material-web) team is working on Material 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-html-material` subproject](compose-html-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 HTML. 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-html-common` subproject](compose-html-common), which may be occasionally updated for the dependent project. diff --git a/compose-html-material/build.gradle.kts b/compose-html-material/build.gradle.kts index 570c7be..08886f3 100644 --- a/compose-html-material/build.gradle.kts +++ b/compose-html-material/build.gradle.kts @@ -43,8 +43,8 @@ kotlin { publishing.publications.withType { pomForTeamDefaultOpenSource( project, - "Compose HTML Material", - "Some Material components for Compose HTML" + "Compose HTML Material 2", + "Legacy Material 2 components for Compose HTML" ) { `Shreck Ye`() } diff --git a/settings.gradle.kts b/settings.gradle.kts index 07ef072..3ae8cad 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -2,5 +2,6 @@ rootProject.name = "compose-html-material" include("compose-html-common") include("compose-html-material") +include("compose-html-material3") include("gradle-plugins") project(":gradle-plugins").name = rootProject.name + "-gradle-plugins" From 3a00375c6a1c43f18dbd12461446ae4b8124c955 Mon Sep 17 00:00:00 2001 From: Shreck Ye Date: Mon, 15 Apr 2024 03:14:14 +0800 Subject: [PATCH 05/34] Remove some unnecessary imports --- buildSrc/src/main/kotlin/lib-conventions.gradle.kts | 6 ------ 1 file changed, 6 deletions(-) diff --git a/buildSrc/src/main/kotlin/lib-conventions.gradle.kts b/buildSrc/src/main/kotlin/lib-conventions.gradle.kts index d1e548e..a8a4e96 100644 --- a/buildSrc/src/main/kotlin/lib-conventions.gradle.kts +++ b/buildSrc/src/main/kotlin/lib-conventions.gradle.kts @@ -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") From d6d797ef50611ace39cccab125d2b23727885311 Mon Sep 17 00:00:00 2001 From: Shreck Ye Date: Mon, 15 Apr 2024 03:49:43 +0800 Subject: [PATCH 06/34] Set up the `compose-html-material3` module and move code (the `MdButton` composable) here from "compose-multiplatform-material" Run `kotlinUpgradeYarnLock` as well. The source commit: https://github.com/huanshankeji/compose-multiplatform-material/commit/a778036003f3360486ee12217879587aaa06505f --- .../main/kotlin/VersionsAndDependencies.kt | 3 + .../main/kotlin/lib-conventions.gradle.kts | 1 + compose-html-common/build.gradle.kts | 3 +- compose-html-material/build.gradle.kts | 2 +- compose-html-material3/build.gradle.kts | 30 ++++++++ .../compose/html/material3/MdButton.kt | 69 +++++++++++++++++++ kotlin-js-store/yarn.lock | 50 ++++++++++++++ 7 files changed, 156 insertions(+), 2 deletions(-) create mode 100644 compose-html-material3/build.gradle.kts create mode 100644 compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MdButton.kt diff --git a/buildSrc/src/main/kotlin/VersionsAndDependencies.kt b/buildSrc/src/main/kotlin/VersionsAndDependencies.kt index d8ed8e1..86ae049 100644 --- a/buildSrc/src/main/kotlin/VersionsAndDependencies.kt +++ b/buildSrc/src/main/kotlin/VersionsAndDependencies.kt @@ -3,6 +3,9 @@ import com.huanshankeji.CommonDependencies const val projectVersion = "0.3.0-SNAPSHOT" object DependencyVersions { + val kobweb = "0.17.1" + val materialWeb = "1.4.0" + val webcomponents = "2.6.0" val mwc = "0.25.3" diff --git a/buildSrc/src/main/kotlin/lib-conventions.gradle.kts b/buildSrc/src/main/kotlin/lib-conventions.gradle.kts index a8a4e96..66b361d 100644 --- a/buildSrc/src/main/kotlin/lib-conventions.gradle.kts +++ b/buildSrc/src/main/kotlin/lib-conventions.gradle.kts @@ -6,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" diff --git a/compose-html-common/build.gradle.kts b/compose-html-common/build.gradle.kts index be6d98f..5830404 100644 --- a/compose-html-common/build.gradle.kts +++ b/compose-html-common/build.gradle.kts @@ -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()) // TODO consider removing this to reduce the bundle size when possible } } } diff --git a/compose-html-material/build.gradle.kts b/compose-html-material/build.gradle.kts index 08886f3..4735f5e 100644 --- a/compose-html-material/build.gradle.kts +++ b/compose-html-material/build.gradle.kts @@ -7,7 +7,7 @@ plugins { kotlin { sourceSets { - val jsMain by getting { + jsMain { dependencies { implementation(compose.html.core) implementation(compose.runtime) diff --git a/compose-html-material3/build.gradle.kts b/compose-html-material3/build.gradle.kts new file mode 100644 index 0000000..afff985 --- /dev/null +++ b/compose-html-material3/build.gradle.kts @@ -0,0 +1,30 @@ +import com.huanshankeji.team.`Shreck Ye` +import com.huanshankeji.team.pomForTeamDefaultOpenSource + +plugins { + `lib-conventions` +} + +kotlin { + sourceSets { + jsMain { + dependencies { + implementation(compose.html.core) + implementation(compose.runtime) + implementation(project(":compose-html-common")) + + implementation(npm("@material/web", DependencyVersions.materialWeb)) + } + } + } +} + +publishing.publications.withType { + pomForTeamDefaultOpenSource( + project, + "Compose HTML Material 3", + "Material 3 components for Compose HTML" + ) { + `Shreck Ye`() + } +} diff --git a/compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MdButton.kt b/compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MdButton.kt new file mode 100644 index 0000000..4743877 --- /dev/null +++ b/compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MdButton.kt @@ -0,0 +1,69 @@ +package com.huanshankeji.compose.html.material3 + +import androidx.compose.runtime.Composable +import com.varabyte.kobweb.compose.css.disabled +import org.jetbrains.compose.web.attributes.AttrsScope +import org.jetbrains.compose.web.dom.ElementScope +import org.jetbrains.compose.web.dom.TagElement +import org.w3c.dom.HTMLElement +import org.w3c.dom.HTMLFormElement + +external fun require(module: String): dynamic + +/* +// TODO not working +@JsModule("@material/web/button/elevated-button.js") +external class MdElevatedButton /* : Element */ // TODO + +private var toImport = true +*/ + +// https://github.com/material-components/material-web/blob/main/docs/components/button.md +@Composable +fun MdElevatedButton( + disabled: Boolean? = null, + href: String? = null, + target: String? = null, + trailingIcon: Boolean? = null, + hasIcon: Boolean? = null, + type: String? = null, + value: String? = null, + name: String? = null, + form: HTMLFormElement? = null, + ariaLabel: String? = null, + attrs: (AttrsScope.() -> Unit)?, + content: (@Composable MdButtonScope.() -> Unit)? +) { + /* + // TODO not working + if (toImport) { + MdElevatedButton() + toImport = false + } + */ + // It seems there is no need to put this in an effect block, because it seems on Compose HTML recomposition happens exactly when there is a need to re-invoke a composable. + require("@material/web/button/elevated-button.js") + + //TagElement({ MdElevatedButton().asDynamic() }, { TODO() }) { TODO() } + @Suppress("RemoveExplicitTypeArguments") + TagElement("md-elevated-button", { + disabled?.let { disabled(it) } + href?.let { attr("href", it) } + target?.let { attr("target", it) } + trailingIcon?.let { attr("trailing-icon", it.toString()) } + hasIcon?.let { attr("has-icon", it.toString()) } + type?.let { attr("type", it) } + value?.let { attr("value", it) } + name?.let { attr("name", it) } + form?.let { TODO() } + // ariaLabel?.let { TODO() } // TODO remove as it's a universal attribute + attrs?.invoke(this) + }, content?.let { + { MdButtonScope(this).it() } + }) +} + +class MdButtonScope(val elementScope: ElementScope) { + fun AttrsScope<*>.slotIcon() = + attr("slot", "icon") +} diff --git a/kotlin-js-store/yarn.lock b/kotlin-js-store/yarn.lock index 509fe20..4568224 100644 --- a/kotlin-js-store/yarn.lock +++ b/kotlin-js-store/yarn.lock @@ -70,6 +70,11 @@ "@jridgewell/resolve-uri" "3.1.0" "@jridgewell/sourcemap-codec" "1.4.14" +"@lit-labs/ssr-dom-shim@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@lit-labs/ssr-dom-shim/-/ssr-dom-shim-1.2.0.tgz#353ce4a76c83fadec272ea5674ede767650762fd" + integrity sha512-yWJKmpGE6lUURKAaIltoPIE/wrbY3TEkqQt+X0m+7fQNnAv0keydnYvbiJFP1PnMhizmIWRWOG5KLhYyc/xl+g== + "@lit/reactive-element@1.0.0-rc.4": version "1.0.0-rc.4" resolved "https://registry.yarnpkg.com/@lit/reactive-element/-/reactive-element-1.0.0-rc.4.tgz#3473f6a687e9925fc2e9ff1b716a86b5f4b576ad" @@ -80,6 +85,13 @@ resolved "https://registry.yarnpkg.com/@lit/reactive-element/-/reactive-element-1.3.2.tgz#43e470537b6ec2c23510c07812616d5aa27a17cd" integrity sha512-A2e18XzPMrIh35nhIdE4uoqRzoIpEU5vZYuQN4S3Ee1zkGdYC27DP12pewbw/RLgPHzaE4kx/YqxMzebOpm0dA== +"@lit/reactive-element@^2.0.4": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@lit/reactive-element/-/reactive-element-2.0.4.tgz#8f2ed950a848016383894a26180ff06c56ae001b" + integrity sha512-GFn91inaUa2oHLak8awSIigYz0cU0Payr1rcFsrkf5OJ5eSPxElyZfKh0f2p9FsTiZWXQdWGJeXZICEfXXYSXQ== + dependencies: + "@lit-labs/ssr-dom-shim" "^1.2.0" + "@material/animation@14.0.0-canary.261f2db59.0": version "14.0.0-canary.261f2db59.0" resolved "https://registry.yarnpkg.com/@material/animation/-/animation-14.0.0-canary.261f2db59.0.tgz#1e3897a25dc4264afd5beb40f8040686276903fc" @@ -696,6 +708,14 @@ "@material/theme" "14.0.0-canary.261f2db59.0" tslib "^2.1.0" +"@material/web@1.4.0": + version "1.4.0" + resolved "https://registry.yarnpkg.com/@material/web/-/web-1.4.0.tgz#2354ae1bcbfd1a81bececfdc35f5bfe8cbce0777" + integrity sha512-+rnQLUc/vsu7vnkr8XxbEhNVEcdkaYxNjykZ18w/nUMrYTEvAi4TRQJAYeEUXMwRcO3mEXBsCKOtHZ+cbmxTLw== + dependencies: + lit "^2.7.4 || ^3.0.0" + tslib "^2.4.0" + "@socket.io/component-emitter@~3.1.0": version "3.1.0" resolved "https://registry.yarnpkg.com/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz#96116f2a912e0c02817345b3c10751069920d553" @@ -1793,6 +1813,15 @@ lit-element@^3.2.0: "@lit/reactive-element" "^1.3.0" lit-html "^2.2.0" +lit-element@^4.0.4: + version "4.0.4" + resolved "https://registry.yarnpkg.com/lit-element/-/lit-element-4.0.4.tgz#e0b37ebbe2394bcb9578d611a409f49475dff361" + integrity sha512-98CvgulX6eCPs6TyAIQoJZBCQPo80rgXR+dVBs61cstJXqtI+USQZAbA4gFHh6L/mxBx9MrgPLHLsUgDUHAcCQ== + dependencies: + "@lit-labs/ssr-dom-shim" "^1.2.0" + "@lit/reactive-element" "^2.0.4" + lit-html "^3.1.2" + lit-html@^2.2.0: version "2.2.5" resolved "https://registry.yarnpkg.com/lit-html/-/lit-html-2.2.5.tgz#e2b4fbdb3b57e38a3bce23c8473d72ba0e652ed8" @@ -1800,6 +1829,13 @@ lit-html@^2.2.0: dependencies: "@types/trusted-types" "^2.0.2" +lit-html@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/lit-html/-/lit-html-3.1.2.tgz#6655ce82367472de7680c62b1bcb0beb0e426fa1" + integrity sha512-3OBZSUrPnAHoKJ9AMjRL/m01YJxQMf+TMHanNtTHG68ubjnZxK0RFl102DPzsw4mWnHibfZIBJm3LWCZ/LmMvg== + dependencies: + "@types/trusted-types" "^2.0.2" + lit@^2.0.0: version "2.2.5" resolved "https://registry.yarnpkg.com/lit/-/lit-2.2.5.tgz#60e8dd5b751fe31f849c64f74f1784a88235d664" @@ -1809,6 +1845,15 @@ lit@^2.0.0: lit-element "^3.2.0" lit-html "^2.2.0" +"lit@^2.7.4 || ^3.0.0": + version "3.1.2" + resolved "https://registry.yarnpkg.com/lit/-/lit-3.1.2.tgz#f276258e8a56593f1d834a5fd00a7eb5e891ae73" + integrity sha512-VZx5iAyMtX7CV4K8iTLdCkMaYZ7ipjJZ0JcSdJ0zIdGxxyurjIn7yuuSxNBD7QmjvcNJwr0JS4cAdAtsy7gZ6w== + dependencies: + "@lit/reactive-element" "^2.0.4" + lit-element "^4.0.4" + lit-html "^3.1.2" + loader-runner@^4.2.0: version "4.3.0" resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-4.3.0.tgz#c1b4a163b99f614830353b16755e7149ac2314e1" @@ -2410,6 +2455,11 @@ tslib@^2.0.1, tslib@^2.1.0: resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3" integrity sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ== +tslib@^2.4.0: + version "2.6.2" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae" + integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q== + type-is@~1.6.18: version "1.6.18" resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" From 9371c81b4b8324e7c59cc00345b347b56690ba3f Mon Sep 17 00:00:00 2001 From: Shreck Ye Date: Mon, 15 Apr 2024 18:58:30 +0800 Subject: [PATCH 07/34] Improve `MdElevatedButton` properties (parameters) --- .../com/huanshankeji/compose/web/attributes/AttrsScope.kt | 6 ++++-- .../com/huanshankeji/compose/html/material3/MdButton.kt | 7 ++----- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/AttrsScope.kt b/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/AttrsScope.kt index 25347c8..0c52fc4 100644 --- a/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/AttrsScope.kt +++ b/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/AttrsScope.kt @@ -1,7 +1,9 @@ package com.huanshankeji.compose.web.attributes import org.jetbrains.compose.web.attributes.AttrsScope -import org.w3c.dom.HTMLElement -fun AttrsScope.attr(attr: String, isPresent: Boolean = true) = +fun AttrsScope<*>.attr(attr: String, isPresent: Boolean = true) = attr(attr, isPresent.toString()) + +fun AttrsScope<*>.ariaLabel(value: String) = + attr("aria-label", value) diff --git a/compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MdButton.kt b/compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MdButton.kt index 4743877..9b55423 100644 --- a/compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MdButton.kt +++ b/compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MdButton.kt @@ -6,7 +6,6 @@ import org.jetbrains.compose.web.attributes.AttrsScope import org.jetbrains.compose.web.dom.ElementScope import org.jetbrains.compose.web.dom.TagElement import org.w3c.dom.HTMLElement -import org.w3c.dom.HTMLFormElement external fun require(module: String): dynamic @@ -29,8 +28,7 @@ fun MdElevatedButton( type: String? = null, value: String? = null, name: String? = null, - form: HTMLFormElement? = null, - ariaLabel: String? = null, + form: String? = null, // The form ID attrs: (AttrsScope.() -> Unit)?, content: (@Composable MdButtonScope.() -> Unit)? ) { @@ -55,8 +53,7 @@ fun MdElevatedButton( type?.let { attr("type", it) } value?.let { attr("value", it) } name?.let { attr("name", it) } - form?.let { TODO() } - // ariaLabel?.let { TODO() } // TODO remove as it's a universal attribute + form?.let { attr("form", it) } attrs?.invoke(this) }, content?.let { { MdButtonScope(this).it() } From ebca4bc99ceee094314c6655c1aaa6b9403a5fd4 Mon Sep 17 00:00:00 2001 From: Shreck Ye Date: Mon, 15 Apr 2024 19:18:03 +0800 Subject: [PATCH 08/34] Rename "compose-html-material" into "compose-html-material-legacy" --- README.md | 10 +++++++--- .../build.gradle.kts | 0 .../huanshankeji/compose/web/material/Components.kt | 0 .../com/huanshankeji/compose/web/material/Layouts.kt | 0 .../huanshankeji/compose/web/material/MwcRequires.kt | 0 .../com/huanshankeji/compose/web/material/Styles.kt | 0 .../jsMain/kotlin/com/huanshankeji/material/Colors.kt | 0 .../compose-html-material-conventions.gradle.kts | 2 +- settings.gradle.kts | 2 +- 9 files changed, 9 insertions(+), 5 deletions(-) rename {compose-html-material => compose-html-material-legacy}/build.gradle.kts (100%) rename {compose-html-material => compose-html-material-legacy}/src/jsMain/kotlin/com/huanshankeji/compose/web/material/Components.kt (100%) rename {compose-html-material => compose-html-material-legacy}/src/jsMain/kotlin/com/huanshankeji/compose/web/material/Layouts.kt (100%) rename {compose-html-material => compose-html-material-legacy}/src/jsMain/kotlin/com/huanshankeji/compose/web/material/MwcRequires.kt (100%) rename {compose-html-material => compose-html-material-legacy}/src/jsMain/kotlin/com/huanshankeji/compose/web/material/Styles.kt (100%) rename {compose-html-material => compose-html-material-legacy}/src/jsMain/kotlin/com/huanshankeji/material/Colors.kt (100%) diff --git a/README.md b/README.md index c845e75..0b5b958 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Compose HTML Material -[![Maven Central](https://img.shields.io/maven-central/v/com.huanshankeji/compose-html-material)](https://search.maven.org/artifact/com.huanshankeji/compose-html-material) +[![Maven Central](https://img.shields.io/maven-central/v/com.huanshankeji/compose-html-material3)](https://search.maven.org/artifact/com.huanshankeji/compose-html-material) [![Gradle Plugin Portal](https://img.shields.io/gradle-plugin-portal/v/com.huanshankeji.compose-html-material-conventions)](https://plugins.gradle.org/plugin/com.huanshankeji.compose-html-material-conventions) Some Material components for Compose HTML, with legacy Material 2 wrapper components based on [the obsolete `mwc` branch of Material Web](https://github.com/material-components/material-web/tree/mwc) (preferred) and [Material Components for the web (or material-components-web, or `mdc`)](https://github.com/material-components/material-components-web) (fallback), and Material 3 wrapper components based on [Material Web](https://github.com/material-components/material-web) @@ -9,7 +9,7 @@ Some Material components for Compose HTML, with legacy Material 2 wrapper compon **The Material 2 portion of this project is not currently under active development. Here is a list of reasons and alternatives:** -1. The [material-web](https://github.com/material-components/material-web) team is working on Material 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-html-material` subproject](compose-html-material) but not updated. +1. The [material-web](https://github.com/material-components/material-web) team is working on Material 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-html-material-legacy` subproject](compose-html-material-legacy) 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 HTML. 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-html-common` subproject](compose-html-common), which may be occasionally updated for the dependent project. @@ -22,13 +22,17 @@ Some configurations are needed to use this library due to the immaturities of th Prior to v0.3.0: ```kotlin +implementation("com.huanshankeji:compose-web-common:$version") implementation("com.huanshankeji:compose-web-material:$version") ``` Since v0.3.0: ```kotlin -implementation("com.huanshankeji:compose-html-material:$version") +implementation("com.huanshankeji:compose-html-common:$version") +implementation("com.huanshankeji:compose-html-material3:$version") + +implementation("com.huanshankeji:compose-html-material-legacy:$version") // Legacy Material 2 ``` ### In code diff --git a/compose-html-material/build.gradle.kts b/compose-html-material-legacy/build.gradle.kts similarity index 100% rename from compose-html-material/build.gradle.kts rename to compose-html-material-legacy/build.gradle.kts diff --git a/compose-html-material/src/jsMain/kotlin/com/huanshankeji/compose/web/material/Components.kt b/compose-html-material-legacy/src/jsMain/kotlin/com/huanshankeji/compose/web/material/Components.kt similarity index 100% rename from compose-html-material/src/jsMain/kotlin/com/huanshankeji/compose/web/material/Components.kt rename to compose-html-material-legacy/src/jsMain/kotlin/com/huanshankeji/compose/web/material/Components.kt diff --git a/compose-html-material/src/jsMain/kotlin/com/huanshankeji/compose/web/material/Layouts.kt b/compose-html-material-legacy/src/jsMain/kotlin/com/huanshankeji/compose/web/material/Layouts.kt similarity index 100% rename from compose-html-material/src/jsMain/kotlin/com/huanshankeji/compose/web/material/Layouts.kt rename to compose-html-material-legacy/src/jsMain/kotlin/com/huanshankeji/compose/web/material/Layouts.kt diff --git a/compose-html-material/src/jsMain/kotlin/com/huanshankeji/compose/web/material/MwcRequires.kt b/compose-html-material-legacy/src/jsMain/kotlin/com/huanshankeji/compose/web/material/MwcRequires.kt similarity index 100% rename from compose-html-material/src/jsMain/kotlin/com/huanshankeji/compose/web/material/MwcRequires.kt rename to compose-html-material-legacy/src/jsMain/kotlin/com/huanshankeji/compose/web/material/MwcRequires.kt diff --git a/compose-html-material/src/jsMain/kotlin/com/huanshankeji/compose/web/material/Styles.kt b/compose-html-material-legacy/src/jsMain/kotlin/com/huanshankeji/compose/web/material/Styles.kt similarity index 100% rename from compose-html-material/src/jsMain/kotlin/com/huanshankeji/compose/web/material/Styles.kt rename to compose-html-material-legacy/src/jsMain/kotlin/com/huanshankeji/compose/web/material/Styles.kt diff --git a/compose-html-material/src/jsMain/kotlin/com/huanshankeji/material/Colors.kt b/compose-html-material-legacy/src/jsMain/kotlin/com/huanshankeji/material/Colors.kt similarity index 100% rename from compose-html-material/src/jsMain/kotlin/com/huanshankeji/material/Colors.kt rename to compose-html-material-legacy/src/jsMain/kotlin/com/huanshankeji/material/Colors.kt diff --git a/gradle-plugins/src/main/kotlin/com/huanshankeji/compose-html-material-conventions.gradle.kts b/gradle-plugins/src/main/kotlin/com/huanshankeji/compose-html-material-conventions.gradle.kts index 6626d14..561bafe 100644 --- a/gradle-plugins/src/main/kotlin/com/huanshankeji/compose-html-material-conventions.gradle.kts +++ b/gradle-plugins/src/main/kotlin/com/huanshankeji/compose-html-material-conventions.gradle.kts @@ -10,7 +10,7 @@ kotlin { sourceSets { val jsMain by getting { dependencies { - implementation("com.huanshankeji:compose-html-material:$projectVersion") + implementation("com.huanshankeji:compose-html-material-legacy:$projectVersion") implementation(devNpm("css-loader", NpmDevDependencyVersions.cssLoader)) implementation(devNpm("extract-loader", NpmDevDependencyVersions.extractLoader)) diff --git a/settings.gradle.kts b/settings.gradle.kts index 3ae8cad..4ebf6ef 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,7 +1,7 @@ rootProject.name = "compose-html-material" include("compose-html-common") -include("compose-html-material") +include("compose-html-material-legacy") include("compose-html-material3") include("gradle-plugins") project(":gradle-plugins").name = rootProject.name + "-gradle-plugins" From 4265ae68820731411d71b41159bd383769147579 Mon Sep 17 00:00:00 2001 From: Shreck Ye Date: Wed, 24 Apr 2024 12:25:12 +0800 Subject: [PATCH 09/34] Remove the Coroutines dependency resolving a TODO and remove `LaunchedRefEffect` as `DisposableRefEffect` is already deprecated The purpose of the TODO is actually invalid because `compose.html.core` depends on Coroutines already. --- compose-html-common/build.gradle.kts | 2 +- .../huanshankeji/compose/web/dom/ElementScope.kt | 15 --------------- 2 files changed, 1 insertion(+), 16 deletions(-) delete mode 100644 compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/dom/ElementScope.kt diff --git a/compose-html-common/build.gradle.kts b/compose-html-common/build.gradle.kts index 5830404..0b34ba0 100644 --- a/compose-html-common/build.gradle.kts +++ b/compose-html-common/build.gradle.kts @@ -12,7 +12,7 @@ kotlin { implementation(compose.html.core) implementation(compose.runtime) api("com.varabyte.kobweb:compose-html-ext:${DependencyVersions.kobweb}") - implementation(commonDependencies.kotlinx.coroutines.core()) // TODO consider removing this to reduce the bundle size when possible + //implementation(commonDependencies.kotlinx.coroutines.core()) } } } diff --git a/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/dom/ElementScope.kt b/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/dom/ElementScope.kt deleted file mode 100644 index cf64f59..0000000 --- a/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/dom/ElementScope.kt +++ /dev/null @@ -1,15 +0,0 @@ -package com.huanshankeji.compose.web.dom - -import androidx.compose.runtime.Composable -import androidx.compose.runtime.NonRestartableComposable -import kotlinx.coroutines.CoroutineScope -import org.jetbrains.compose.web.dom.ElementScope -import org.w3c.dom.Element - -@Composable -@NonRestartableComposable -fun ElementScope.LaunchedRefEffect( - vararg keys: Any?, - block: suspend CoroutineScope.(TElement) -> Unit -) = - TODO() as Unit From 210aa21a70f36856f06447a6a5af74f07d06d6b3 Mon Sep 17 00:00:00 2001 From: Shreck Ye Date: Wed, 24 Apr 2024 16:12:20 +0800 Subject: [PATCH 10/34] Bump dependency versions and run `kotlinUpgradeYarnLock` --- buildSrc/build.gradle.kts | 2 +- buildSrc/src/main/kotlin/VersionsAndDependencies.kt | 4 ++-- kotlin-js-store/yarn.lock | 8 ++++---- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index 7b5a11e..8740221 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -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") diff --git a/buildSrc/src/main/kotlin/VersionsAndDependencies.kt b/buildSrc/src/main/kotlin/VersionsAndDependencies.kt index 86ae049..7f6ad52 100644 --- a/buildSrc/src/main/kotlin/VersionsAndDependencies.kt +++ b/buildSrc/src/main/kotlin/VersionsAndDependencies.kt @@ -3,8 +3,8 @@ import com.huanshankeji.CommonDependencies const val projectVersion = "0.3.0-SNAPSHOT" object DependencyVersions { - val kobweb = "0.17.1" - val materialWeb = "1.4.0" + val kobweb = "0.17.3" + val materialWeb = "1.4.1" val webcomponents = "2.6.0" val mwc = "0.25.3" diff --git a/kotlin-js-store/yarn.lock b/kotlin-js-store/yarn.lock index 4568224..bf0ba8b 100644 --- a/kotlin-js-store/yarn.lock +++ b/kotlin-js-store/yarn.lock @@ -708,10 +708,10 @@ "@material/theme" "14.0.0-canary.261f2db59.0" tslib "^2.1.0" -"@material/web@1.4.0": - version "1.4.0" - resolved "https://registry.yarnpkg.com/@material/web/-/web-1.4.0.tgz#2354ae1bcbfd1a81bececfdc35f5bfe8cbce0777" - integrity sha512-+rnQLUc/vsu7vnkr8XxbEhNVEcdkaYxNjykZ18w/nUMrYTEvAi4TRQJAYeEUXMwRcO3mEXBsCKOtHZ+cbmxTLw== +"@material/web@1.4.1": + version "1.4.1" + resolved "https://registry.yarnpkg.com/@material/web/-/web-1.4.1.tgz#116480759d0b5815ea181086d32cc3ccb54a30f6" + integrity sha512-17MZA6Bt7ie6uDc5cVEGtm6frQfm7ASLGVJhJuYJ0W2Fs7Zogd8wJ3ExoYU8jyzv8LEXcfvnZKcvr8dlquGsig== dependencies: lit "^2.7.4 || ^3.0.0" tslib "^2.4.0" From 036356a7accb5556dc2c21e099a5dbde9c97a1d2 Mon Sep 17 00:00:00 2001 From: Shreck Ye Date: Wed, 24 Apr 2024 18:30:57 +0800 Subject: [PATCH 11/34] Add all the Material Web buttons, extract common CSS attributes, and do some chores --- .../com/huanshankeji/compose/web/Layouts.kt | 17 +- .../web/PreferringKobwebComposeLayoutApi.kt | 9 + .../compose/web/attributes/AttrsScope.kt | 29 +++ .../compose/web/attributes/Types.kt | 5 + .../com/huanshankeji/compose/web/css/CSS.kt | 4 +- .../compose/html/material3/MdButton.kt | 184 +++++++++++++++--- 6 files changed, 213 insertions(+), 35 deletions(-) create mode 100644 compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/PreferringKobwebComposeLayoutApi.kt create mode 100644 compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/Types.kt diff --git a/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/Layouts.kt b/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/Layouts.kt index 4041035..f87d670 100644 --- a/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/Layouts.kt +++ b/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/Layouts.kt @@ -30,11 +30,13 @@ fun Flexbox( } } + attrs, content) -@Composable +@PreferringKobwebComposeLayoutApi @Deprecated(WITH_STYLES_DEPRECATED_MESSAGE) +@Composable fun FlexboxS(styles: Styles? = null, content: ContentBuilder) = Flexbox(styles.wrapInAttrs(), content) +@PreferringKobwebComposeLayoutApi @Composable fun Column( attrs: AttrBuilderContext? = null, @@ -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) = Column(styles.wrapInAttrs(), fitContent, content) +@PreferringKobwebComposeLayoutApi @Composable fun ColumnWithSpaceBetween( attrs: AttrBuilderContext? = null, @@ -66,6 +70,7 @@ fun ColumnWithSpaceBetween( } + attrs, fitContent, content) +@PreferringKobwebComposeLayoutApi @Composable fun Row( attrs: AttrBuilderContext? = null, @@ -77,14 +82,16 @@ fun Row( } } + attrs, content) -@Composable +@PreferringKobwebComposeLayoutApi @Deprecated(WITH_STYLES_DEPRECATED_MESSAGE) +@Composable fun RowS( styles: Styles? = null, content: ContentBuilder ) = Row(styles.wrapInAttrs(), content) +@PreferringKobwebComposeLayoutApi @Composable fun RowWithSpaceBetween( attrs: AttrBuilderContext? = null, @@ -96,6 +103,7 @@ fun RowWithSpaceBetween( } } + attrs, content) +@PreferringKobwebComposeLayoutApi @Composable fun ColumnWithGaps( attrs: AttrBuilderContext? = null, @@ -109,6 +117,7 @@ fun ColumnWithGaps( } } + attrs, fitContent, content) +@PreferringKobwebComposeLayoutApi @Composable fun RowWithGaps( attrs: AttrBuilderContext? = null, @@ -158,6 +167,8 @@ fun FrGrid( } }, content) +@PreferringKobwebComposeLayoutApi +@Deprecated("This API is not implemented yet.") @Composable fun Spacer(numPxs: Int) = TODO() as Unit diff --git a/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/PreferringKobwebComposeLayoutApi.kt b/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/PreferringKobwebComposeLayoutApi.kt new file mode 100644 index 0000000..3407e42 --- /dev/null +++ b/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/PreferringKobwebComposeLayoutApi.kt @@ -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 \ No newline at end of file diff --git a/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/AttrsScope.kt b/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/AttrsScope.kt index 0c52fc4..a66b865 100644 --- a/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/AttrsScope.kt +++ b/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/AttrsScope.kt @@ -1,5 +1,6 @@ package com.huanshankeji.compose.web.attributes +import com.varabyte.kobweb.compose.css.disabled import org.jetbrains.compose.web.attributes.AttrsScope fun AttrsScope<*>.attr(attr: String, isPresent: Boolean = true) = @@ -7,3 +8,31 @@ fun AttrsScope<*>.attr(attr: String, isPresent: Boolean = true) = fun AttrsScope<*>.ariaLabel(value: String) = attr("aria-label", value) + +fun AttrsScope<*>.disabled(disabled: Boolean?) { + disabled?.let { disabled(it) } +} + +fun AttrsScope<*>.href(href: String?) { + href?.let { attr("href", it) } +} + +fun AttrsScope<*>.target(target: String?) { + target?.let { attr("target", it) } +} + +fun AttrsScope<*>.type(type: String?) { + type?.let { attr("type", it) } +} + +fun AttrsScope<*>.value(value: String?) { + value?.let { attr("value", it) } +} + +fun AttrsScope<*>.form(formId: String?) { + formId?.let { attr("form", it) } +} + +fun AttrsScope<*>.name(name: String?) { + name?.let { attr("name", it) } +} diff --git a/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/Types.kt b/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/Types.kt new file mode 100644 index 0000000..e287f21 --- /dev/null +++ b/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/Types.kt @@ -0,0 +1,5 @@ +package com.huanshankeji.compose.web.attributes + +import org.jetbrains.compose.web.attributes.AttrsScope + +typealias Attrs = AttrsScope.() -> Unit diff --git a/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/css/CSS.kt b/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/css/CSS.kt index e92972d..bde0bd4 100644 --- a/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/css/CSS.kt +++ b/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/css/CSS.kt @@ -2,10 +2,10 @@ package com.huanshankeji.compose.web.css -import org.jetbrains.compose.web.css.StyleBuilder import org.jetbrains.compose.web.css.StylePropertyEnum +import org.jetbrains.compose.web.css.StyleScope -fun StyleBuilder.visibility(visibility: Visibility) = +fun StyleScope.visibility(visibility: Visibility) = property("visibility", visibility) interface Visibility : StylePropertyEnum { diff --git a/compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MdButton.kt b/compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MdButton.kt index 9b55423..aba9888 100644 --- a/compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MdButton.kt +++ b/compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MdButton.kt @@ -1,7 +1,7 @@ package com.huanshankeji.compose.html.material3 import androidx.compose.runtime.Composable -import com.varabyte.kobweb.compose.css.disabled +import com.huanshankeji.compose.web.attributes.* import org.jetbrains.compose.web.attributes.AttrsScope import org.jetbrains.compose.web.dom.ElementScope import org.jetbrains.compose.web.dom.TagElement @@ -9,6 +9,8 @@ import org.w3c.dom.HTMLElement external fun require(module: String): dynamic +// https://github.com/material-components/material-web/blob/main/docs/components/button.md + /* // TODO not working @JsModule("@material/web/button/elevated-button.js") @@ -17,9 +19,92 @@ external class MdElevatedButton /* : Element */ // TODO private var toImport = true */ -// https://github.com/material-components/material-web/blob/main/docs/components/button.md +private fun commonButtonAttrs( + disabled: Boolean?, + href: String?, + target: String?, + trailingIcon: Boolean?, + hasIcon: Boolean?, + type: String?, + value: String?, + name: String?, + form: String?, + attrs: Attrs? +): Attrs = + { + disabled(disabled) + href(href) + target(target) + trailingIcon?.let { attr("trailing-icon", it.toString()) } + hasIcon?.let { attr("has-icon", it.toString()) } + type(type) + value(value) + name(name) + form(form) + attrs?.invoke(this) + } + +private fun (@Composable MdButtonScope.() -> Unit)?.toElementScopeContent(): (@Composable ElementScope.() -> Unit)? = + this?.let { + { MdButtonScope(this).it() } + } + +@Composable +private fun CommonButton( + module: String, + tagName: String, + disabled: Boolean?, + href: String?, + target: String?, + trailingIcon: Boolean?, + hasIcon: Boolean?, + type: String?, + value: String?, + name: String?, + form: String?, // The form ID + attrs: Attrs?, + content: (@Composable MdButtonScope.() -> Unit)? +) { + /* + // TODO not working + if (toImport) { + MdElevatedButton() + toImport = false + } + */ + // It seems there is no need to put this in an effect block, because it seems on Compose HTML recomposition happens exactly when there is a need to re-invoke a composable. + require(module) + + //TagElement({ MdElevatedButton().asDynamic() }, { TODO() }) { TODO() } + TagElement( + tagName, + commonButtonAttrs(disabled, href, target, trailingIcon, hasIcon, type, value, name, form, attrs), + content.toElementScopeContent() + ) +} + @Composable fun MdElevatedButton( + disabled: Boolean? = null, + href: String? = null, + target: String? = null, + trailingIcon: Boolean? = null, + hasIcon: Boolean? = null, + type: String? = null, + value: String? = null, + name: String? = null, + form: String? = null, + attrs: Attrs?, + content: (@Composable MdButtonScope.() -> Unit)? +) = + CommonButton( + "@material/web/button/elevated-button.js", "md-elevated-button", + disabled, href, target, trailingIcon, hasIcon, type, value, name, form, + attrs, content + ) + +@Composable +fun MdFilledButton( disabled: Boolean? = null, href: String? = null, target: String? = null, @@ -29,36 +114,75 @@ fun MdElevatedButton( value: String? = null, name: String? = null, form: String? = null, // The form ID - attrs: (AttrsScope.() -> Unit)?, + attrs: Attrs?, content: (@Composable MdButtonScope.() -> Unit)? -) { - /* - // TODO not working - if (toImport) { - MdElevatedButton() - toImport = false - } - */ - // It seems there is no need to put this in an effect block, because it seems on Compose HTML recomposition happens exactly when there is a need to re-invoke a composable. - require("@material/web/button/elevated-button.js") +) = + CommonButton( + "@material/web/button/filled-button.js", "md-filled-button", + disabled, href, target, trailingIcon, hasIcon, type, value, name, form, + attrs, content + ) + +@Composable +fun MdFilledTonalButton( + disabled: Boolean? = null, + href: String? = null, + target: String? = null, + trailingIcon: Boolean? = null, + hasIcon: Boolean? = null, + type: String? = null, + value: String? = null, + name: String? = null, + form: String? = null, // The form ID + attrs: Attrs?, + content: (@Composable MdButtonScope.() -> Unit)? +) = + CommonButton( + "@material/web/button/filled-tonal-button.js", "md-filled-tonal-button", + disabled, href, target, trailingIcon, hasIcon, type, value, name, form, + attrs, content + ) + +@Composable +fun MdOutlinedButton( + disabled: Boolean? = null, + href: String? = null, + target: String? = null, + trailingIcon: Boolean? = null, + hasIcon: Boolean? = null, + type: String? = null, + value: String? = null, + name: String? = null, + form: String? = null, // The form ID + attrs: Attrs?, + content: (@Composable MdButtonScope.() -> Unit)? +) = + CommonButton( + "@material/web/button/outlined-button.js", "md-outlined-button", + disabled, href, target, trailingIcon, hasIcon, type, value, name, form, + attrs, content + ) + +@Composable +fun MdTextButton( + disabled: Boolean? = null, + href: String? = null, + target: String? = null, + trailingIcon: Boolean? = null, + hasIcon: Boolean? = null, + type: String? = null, + value: String? = null, + name: String? = null, + form: String? = null, // The form ID + attrs: Attrs?, + content: (@Composable MdButtonScope.() -> Unit)? +) = + CommonButton( + "@material/web/button/text-button.js", "md-text-button", + disabled, href, target, trailingIcon, hasIcon, type, value, name, form, + attrs, content + ) - //TagElement({ MdElevatedButton().asDynamic() }, { TODO() }) { TODO() } - @Suppress("RemoveExplicitTypeArguments") - TagElement("md-elevated-button", { - disabled?.let { disabled(it) } - href?.let { attr("href", it) } - target?.let { attr("target", it) } - trailingIcon?.let { attr("trailing-icon", it.toString()) } - hasIcon?.let { attr("has-icon", it.toString()) } - type?.let { attr("type", it) } - value?.let { attr("value", it) } - name?.let { attr("name", it) } - form?.let { attr("form", it) } - attrs?.invoke(this) - }, content?.let { - { MdButtonScope(this).it() } - }) -} class MdButtonScope(val elementScope: ElementScope) { fun AttrsScope<*>.slotIcon() = From 938bf850682974ef6bf7542ea268f6b8b3518166 Mon Sep 17 00:00:00 2001 From: Shreck Ye Date: Thu, 25 Apr 2024 18:46:10 +0800 Subject: [PATCH 12/34] Fix the bug that the added Material 3 buttons don't work by moving `require` out of `CommonButton` it seems to be processed by Webpack, JS `require` only takes constants. Adding Kotlin `inline` to `CommonButton` doesn't work either. --- .../compose/html/material3/MdButton.kt | 58 +++++++++++-------- 1 file changed, 35 insertions(+), 23 deletions(-) diff --git a/compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MdButton.kt b/compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MdButton.kt index aba9888..7be6da2 100644 --- a/compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MdButton.kt +++ b/compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MdButton.kt @@ -51,7 +51,6 @@ private fun (@Composable MdButtonScope.() -> Unit)?.toElementScopeContent(): (@C @Composable private fun CommonButton( - module: String, tagName: String, disabled: Boolean?, href: String?, @@ -64,24 +63,13 @@ private fun CommonButton( form: String?, // The form ID attrs: Attrs?, content: (@Composable MdButtonScope.() -> Unit)? -) { - /* - // TODO not working - if (toImport) { - MdElevatedButton() - toImport = false - } - */ - // It seems there is no need to put this in an effect block, because it seems on Compose HTML recomposition happens exactly when there is a need to re-invoke a composable. - require(module) - +) = //TagElement({ MdElevatedButton().asDynamic() }, { TODO() }) { TODO() } TagElement( tagName, commonButtonAttrs(disabled, href, target, trailingIcon, hasIcon, type, value, name, form, attrs), content.toElementScopeContent() ) -} @Composable fun MdElevatedButton( @@ -96,12 +84,24 @@ fun MdElevatedButton( form: String? = null, attrs: Attrs?, content: (@Composable MdButtonScope.() -> Unit)? -) = +) { + /* + // TODO not working + if (toImport) { + MdElevatedButton() + toImport = false + } + */ + // `require` can't be wrapped in `CommonButton` taken a `module` parameter because it seems to be processed by Webpack, JS `require` only takes constants. + // It seems there is no need to put this in an effect block, because it seems on Compose HTML recomposition happens exactly when there is a need to re-invoke a composable. + require("@material/web/button/elevated-button.js") + CommonButton( - "@material/web/button/elevated-button.js", "md-elevated-button", + "md-elevated-button", disabled, href, target, trailingIcon, hasIcon, type, value, name, form, attrs, content ) +} @Composable fun MdFilledButton( @@ -116,12 +116,15 @@ fun MdFilledButton( form: String? = null, // The form ID attrs: Attrs?, content: (@Composable MdButtonScope.() -> Unit)? -) = +) { + require("@material/web/button/filled-button.js") + CommonButton( - "@material/web/button/filled-button.js", "md-filled-button", + "md-filled-button", disabled, href, target, trailingIcon, hasIcon, type, value, name, form, attrs, content ) +} @Composable fun MdFilledTonalButton( @@ -136,12 +139,15 @@ fun MdFilledTonalButton( form: String? = null, // The form ID attrs: Attrs?, content: (@Composable MdButtonScope.() -> Unit)? -) = +) { + require("@material/web/button/filled-tonal-button.js") + CommonButton( - "@material/web/button/filled-tonal-button.js", "md-filled-tonal-button", + "md-filled-tonal-button", disabled, href, target, trailingIcon, hasIcon, type, value, name, form, attrs, content ) +} @Composable fun MdOutlinedButton( @@ -156,12 +162,15 @@ fun MdOutlinedButton( form: String? = null, // The form ID attrs: Attrs?, content: (@Composable MdButtonScope.() -> Unit)? -) = +) { + require("@material/web/button/outlined-button.js") + CommonButton( - "@material/web/button/outlined-button.js", "md-outlined-button", + "md-outlined-button", disabled, href, target, trailingIcon, hasIcon, type, value, name, form, attrs, content ) +} @Composable fun MdTextButton( @@ -176,12 +185,15 @@ fun MdTextButton( form: String? = null, // The form ID attrs: Attrs?, content: (@Composable MdButtonScope.() -> Unit)? -) = +) { + require("@material/web/button/text-button.js") + CommonButton( - "@material/web/button/text-button.js", "md-text-button", + "md-text-button", disabled, href, target, trailingIcon, hasIcon, type, value, name, form, attrs, content ) +} class MdButtonScope(val elementScope: ElementScope) { From 07c939e4a2e020ef5dbf4e36101177894db1d581 Mon Sep 17 00:00:00 2001 From: Shreck Ye Date: Thu, 25 Apr 2024 22:36:43 +0800 Subject: [PATCH 13/34] Add the `MdCheckbox` composable, add docs for the attributes, and add a new `required` attribute --- .../compose/web/attributes/AttrsScope.kt | 22 ++++++++++ .../attributes/builders/InputAttrsScope.kt | 10 +++++ .../compose/html/material3/MdButton.kt | 2 - .../compose/html/material3/MdCheckbox.kt | 42 +++++++++++++++++++ .../compose/html/material3/Require.kt | 4 ++ 5 files changed, 78 insertions(+), 2 deletions(-) create mode 100644 compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/builders/InputAttrsScope.kt create mode 100644 compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MdCheckbox.kt create mode 100644 compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/Require.kt diff --git a/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/AttrsScope.kt b/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/AttrsScope.kt index a66b865..297f75d 100644 --- a/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/AttrsScope.kt +++ b/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/AttrsScope.kt @@ -3,36 +3,58 @@ package com.huanshankeji.compose.web.attributes import com.varabyte.kobweb.compose.css.disabled import org.jetbrains.compose.web.attributes.AttrsScope +/** + * @see AttrsScope.attr + */ fun AttrsScope<*>.attr(attr: String, isPresent: Boolean = true) = attr(attr, isPresent.toString()) +// https://www.w3schools.com/accessibility/accessibility_labels.php +// https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label fun AttrsScope<*>.ariaLabel(value: String) = attr("aria-label", value) +// https://www.w3schools.com/tags/att_disabled.asp +// https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/disabled fun AttrsScope<*>.disabled(disabled: Boolean?) { disabled?.let { disabled(it) } } +// https://www.w3schools.com/tags/att_href.asp +// https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a#href fun AttrsScope<*>.href(href: String?) { href?.let { attr("href", it) } } +// https://www.w3schools.com/tags/att_target.asp +// https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a#target fun AttrsScope<*>.target(target: String?) { target?.let { attr("target", it) } } +// https://www.w3schools.com/tags/att_input_type.asp +// https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#type fun AttrsScope<*>.type(type: String?) { type?.let { attr("type", it) } } +// https://www.w3schools.com/tags/att_value.asp fun AttrsScope<*>.value(value: String?) { value?.let { attr("value", it) } } +// https://www.w3schools.com/tags/att_form.asp fun AttrsScope<*>.form(formId: String?) { formId?.let { attr("form", it) } } +// https://www.w3schools.com/tags/att_name.asp fun AttrsScope<*>.name(name: String?) { name?.let { attr("name", it) } } + +// https://www.w3schools.com/tags/att_required.asp +// https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/required +fun AttrsScope<*>.required(required: Boolean?) { + required?.let { attr("required", it) } +} diff --git a/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/builders/InputAttrsScope.kt b/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/builders/InputAttrsScope.kt new file mode 100644 index 0000000..6437c18 --- /dev/null +++ b/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/builders/InputAttrsScope.kt @@ -0,0 +1,10 @@ +package com.huanshankeji.compose.web.attributes.builders + +/* +@ComposeWebInternalApi +fun InputAttrsScope.onInput( + listener: (SyntheticInputEvent) -> Unit +) { + registerEventListener(InputEventListener(eventName = EventsListenerScope.INPUT, inputType, listener)) +} +*/ diff --git a/compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MdButton.kt b/compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MdButton.kt index 7be6da2..17221a3 100644 --- a/compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MdButton.kt +++ b/compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MdButton.kt @@ -7,8 +7,6 @@ import org.jetbrains.compose.web.dom.ElementScope import org.jetbrains.compose.web.dom.TagElement import org.w3c.dom.HTMLElement -external fun require(module: String): dynamic - // https://github.com/material-components/material-web/blob/main/docs/components/button.md /* diff --git a/compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MdCheckbox.kt b/compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MdCheckbox.kt new file mode 100644 index 0000000..2748e03 --- /dev/null +++ b/compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MdCheckbox.kt @@ -0,0 +1,42 @@ +package com.huanshankeji.compose.html.material3 + +import androidx.compose.runtime.Composable +import com.huanshankeji.compose.web.attributes.* +import org.jetbrains.compose.web.dom.TagElement +import org.w3c.dom.HTMLElement + +// https://github.com/material-components/material-web/blob/main/docs/components/checkbox.md + +enum class MdCheckboxState { + Unchecked, Checked, Intermediate +} + +@Composable +fun MdCheckbox( + state: MdCheckboxState, + disabled: Boolean? = null, + required: Boolean? = null, + value: String? = null, + form: String? = null, + //labels : NodeList? = null, // This is a read-only property. See https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement/labels. + //validity : ValidityState? = null, // This is a read-only property. See https://developer.mozilla.org/en-US/docs/Web/API/HTMLObjectElement/validity. + //validationMessage : String? = null, // This is a read-only property. See https://developer.mozilla.org/en-US/docs/Web/API/HTMLObjectElement/validationMessage. + //willValidate : Boolean? = null, // This is a read-only property. See https://developer.mozilla.org/en-US/docs/Web/API/HTMLObjectElement/willValidate. + attrs: Attrs? = null +) { + require("@material/web/checkbox/checkbox.js") + + TagElement("md-checkbox", { + attr("touch-target", "wrapper") + when (state) { + MdCheckboxState.Unchecked -> Unit + MdCheckboxState.Checked -> attr("checked") + MdCheckboxState.Intermediate -> attr("intermediate") + } + disabled(disabled) + required(required) + value(value) + form(form) + attrs?.invoke(this) + }, null) +} diff --git a/compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/Require.kt b/compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/Require.kt new file mode 100644 index 0000000..47c646c --- /dev/null +++ b/compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/Require.kt @@ -0,0 +1,4 @@ +package com.huanshankeji.compose.html.material3 + +// TODO use the one in "kotlin-common" +external fun require(module: String): dynamic From 29c3d4435e724a6eadd143b4c0862bab2bce5607 Mon Sep 17 00:00:00 2001 From: Shreck Ye Date: Fri, 26 Apr 2024 15:31:35 +0800 Subject: [PATCH 14/34] Add a comment --- buildSrc/src/main/kotlin/VersionsAndDependencies.kt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/buildSrc/src/main/kotlin/VersionsAndDependencies.kt b/buildSrc/src/main/kotlin/VersionsAndDependencies.kt index 7f6ad52..de9dcc4 100644 --- a/buildSrc/src/main/kotlin/VersionsAndDependencies.kt +++ b/buildSrc/src/main/kotlin/VersionsAndDependencies.kt @@ -6,6 +6,9 @@ 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" From 64de220b52870493d66c4fddb967b7684eae1ea1 Mon Sep 17 00:00:00 2001 From: Shreck Ye Date: Sat, 27 Apr 2024 17:51:21 +0800 Subject: [PATCH 15/34] Add the `MdSwitch` composable, refactor the `MdCheckbox` composable, add more doc and demo links, add `onInput`, and extract 2 attribute conversion functions for `Boolean` --- .../compose/web/attributes/AttrConversion.kt | 9 +++ .../attributes/{AttrsScope.kt => Attrs.kt} | 0 .../web/attributes/EventsListenerScope.kt | 10 ++++ .../attributes/builders/InputAttrsScope.kt | 10 ---- .../compose/html/material3/MdButton.kt | 7 ++- .../compose/html/material3/MdCheckbox.kt | 57 ++++++++++++++---- .../compose/html/material3/MdSwitch.kt | 59 +++++++++++++++++++ 7 files changed, 128 insertions(+), 24 deletions(-) create mode 100644 compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/AttrConversion.kt rename compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/{AttrsScope.kt => Attrs.kt} (100%) create mode 100644 compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/EventsListenerScope.kt delete mode 100644 compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/builders/InputAttrsScope.kt create mode 100644 compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MdSwitch.kt diff --git a/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/AttrConversion.kt b/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/AttrConversion.kt new file mode 100644 index 0000000..b7cdf4f --- /dev/null +++ b/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/AttrConversion.kt @@ -0,0 +1,9 @@ +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 diff --git a/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/AttrsScope.kt b/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/Attrs.kt similarity index 100% rename from compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/AttrsScope.kt rename to compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/Attrs.kt diff --git a/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/EventsListenerScope.kt b/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/EventsListenerScope.kt new file mode 100644 index 0000000..893cc6d --- /dev/null +++ b/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/EventsListenerScope.kt @@ -0,0 +1,10 @@ +package com.huanshankeji.compose.web.attributes + +import androidx.compose.web.events.SyntheticEvent +import org.jetbrains.compose.web.attributes.EventsListenerScope +import org.w3c.dom.events.EventTarget + +fun EventsListenerScope.onInput( + listener: (SyntheticEvent) -> Unit +) = + addEventListener(EventsListenerScope.INPUT, listener) diff --git a/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/builders/InputAttrsScope.kt b/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/builders/InputAttrsScope.kt deleted file mode 100644 index 6437c18..0000000 --- a/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/builders/InputAttrsScope.kt +++ /dev/null @@ -1,10 +0,0 @@ -package com.huanshankeji.compose.web.attributes.builders - -/* -@ComposeWebInternalApi -fun InputAttrsScope.onInput( - listener: (SyntheticInputEvent) -> Unit -) { - registerEventListener(InputEventListener(eventName = EventsListenerScope.INPUT, inputType, listener)) -} -*/ diff --git a/compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MdButton.kt b/compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MdButton.kt index 17221a3..aefeaaa 100644 --- a/compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MdButton.kt +++ b/compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MdButton.kt @@ -6,8 +6,11 @@ import org.jetbrains.compose.web.attributes.AttrsScope import org.jetbrains.compose.web.dom.ElementScope import org.jetbrains.compose.web.dom.TagElement import org.w3c.dom.HTMLElement - -// https://github.com/material-components/material-web/blob/main/docs/components/button.md +/* +https://github.com/material-components/material-web/blob/main/docs/components/button.md +https://material-web.dev/components/button/ +https://material-web.dev/components/button/stories/ +*/ /* // TODO not working diff --git a/compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MdCheckbox.kt b/compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MdCheckbox.kt index 2748e03..5f4ce2e 100644 --- a/compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MdCheckbox.kt +++ b/compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MdCheckbox.kt @@ -5,16 +5,16 @@ import com.huanshankeji.compose.web.attributes.* import org.jetbrains.compose.web.dom.TagElement import org.w3c.dom.HTMLElement -// https://github.com/material-components/material-web/blob/main/docs/components/checkbox.md - -enum class MdCheckboxState { - Unchecked, Checked, Intermediate -} - +/* +https://github.com/material-components/material-web/blob/main/docs/components/checkbox.md +https://material-web.dev/components/checkbox/ +https://material-web.dev/components/checkbox/stories/ +*/ @Composable fun MdCheckbox( - state: MdCheckboxState, + checked: Boolean? = null, disabled: Boolean? = null, + indeterminate: Boolean? = null, required: Boolean? = null, value: String? = null, form: String? = null, @@ -28,15 +28,48 @@ fun MdCheckbox( TagElement("md-checkbox", { attr("touch-target", "wrapper") - when (state) { - MdCheckboxState.Unchecked -> Unit - MdCheckboxState.Checked -> attr("checked") - MdCheckboxState.Intermediate -> attr("intermediate") - } + checked?.let { attr("checked", it) } disabled(disabled) + indeterminate?.let { attr("indeterminate", it) } required(required) value(value) form(form) attrs?.invoke(this) }, null) } + + +enum class MdCheckboxState { + Unchecked, Checked, Indeterminate +} + +@Composable +fun MdCheckbox( + state: MdCheckboxState, + disabled: Boolean? = null, + required: Boolean? = null, + value: String? = null, + form: String? = null, + attrs: Attrs? = null +) { + val checked: Boolean? + val indeterminate: Boolean? + when (state) { + MdCheckboxState.Unchecked -> { + checked = null + indeterminate = null + } + + MdCheckboxState.Checked -> { + checked = true + indeterminate = null + } + + MdCheckboxState.Indeterminate -> { + checked = null + indeterminate = true + } + } + + MdCheckbox(checked, disabled, indeterminate, required, value, form, attrs) +} diff --git a/compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MdSwitch.kt b/compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MdSwitch.kt new file mode 100644 index 0000000..efdc823 --- /dev/null +++ b/compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MdSwitch.kt @@ -0,0 +1,59 @@ +package com.huanshankeji.compose.html.material3 + +import androidx.compose.runtime.Composable +import com.huanshankeji.compose.web.attributes.* +import org.jetbrains.compose.web.dom.Label +import org.jetbrains.compose.web.dom.TagElement +import org.jetbrains.compose.web.dom.Text +import org.w3c.dom.HTMLElement + +/* +https://github.com/material-components/material-web/blob/main/docs/components/switch.md +https://material-web.dev/components/switch/ +https://material-web.dev/components/switch/stories/ +*/ +@Composable +fun MdSwitch( + disabled: Boolean? = null, + selected: Boolean? = null, // `false` won't work here + icons: Boolean? = null, + showOnlySelectedIcon: Boolean? = null, + required: Boolean? = null, + value: String? = null, + name: String? = null, + form: String? = null, + attrs: Attrs? = null +) { + require("@material/web/switch/switch.js") + + TagElement("md-switch", { + disabled(disabled) + selected?.let { attr("selected", it) } + icons?.let { attr("icons", it) } + showOnlySelectedIcon?.let { attr("showOnlySelectedIcon", it) } + required(required) + value(value) + name(name) + form(form) + attrs?.invoke(this) + }, null) +} + +// https://github.com/material-components/material-web/blob/main/docs/components/switch.md#label +@Composable +fun LabelWithMdSwitch( + label: String, + disabled: Boolean? = null, + selected: Boolean? = null, + icons: Boolean? = null, + showOnlySelectedIcon: Boolean? = null, + required: Boolean? = null, + value: String? = null, + name: String? = null, + form: String? = null, + attrs: Attrs? = null +) = + Label { + Text(label) + MdSwitch(disabled, selected, icons, showOnlySelectedIcon, required, value, name, form, attrs) + } From 21add44fe16ab8c834c2b357a19ba98e1334c8ab Mon Sep 17 00:00:00 2001 From: Shreck Ye Date: Sat, 27 Apr 2024 18:51:05 +0800 Subject: [PATCH 16/34] Remove an explicit type argument --- .../kotlin/com/huanshankeji/compose/html/material3/MdSwitch.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MdSwitch.kt b/compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MdSwitch.kt index efdc823..53d9593 100644 --- a/compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MdSwitch.kt +++ b/compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MdSwitch.kt @@ -26,7 +26,7 @@ fun MdSwitch( ) { require("@material/web/switch/switch.js") - TagElement("md-switch", { + TagElement("md-switch", { disabled(disabled) selected?.let { attr("selected", it) } icons?.let { attr("icons", it) } From a91b0b2f39c039a8635a56995e8f518072ec0941 Mon Sep 17 00:00:00 2001 From: Shreck Ye Date: Sun, 28 Apr 2024 22:47:43 +0800 Subject: [PATCH 17/34] Add the `MdFilledTextField` and ``MdOutlinedTextField` composables, examine the existing properties of the Material Web components with attention on their corresponding attributes (affected ones include `name`, `form`, and `showOnlySelectedIcon`), and extract common extensions for treating an `HTMLElement` as an `HTMLInputElement` --- .../compose/web/attributes/Attrs.kt | 86 ++++++- .../compose/web/attributes/EventAttrs.kt | 15 ++ .../web/attributes/EventsListenerScope.kt | 10 - .../com/huanshankeji/compose/web/dom/dom.kt | 9 + .../compose/html/material3/MdButton.kt | 4 +- .../compose/html/material3/MdCheckbox.kt | 10 +- .../compose/html/material3/MdSwitch.kt | 3 +- .../compose/html/material3/MdTextField.kt | 222 ++++++++++++++++++ 8 files changed, 337 insertions(+), 22 deletions(-) create mode 100644 compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/EventAttrs.kt delete mode 100644 compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/EventsListenerScope.kt create mode 100644 compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/dom/dom.kt create mode 100644 compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MdTextField.kt diff --git a/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/Attrs.kt b/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/Attrs.kt index 297f75d..6a074c7 100644 --- a/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/Attrs.kt +++ b/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/Attrs.kt @@ -2,6 +2,8 @@ package com.huanshankeji.compose.web.attributes import com.varabyte.kobweb.compose.css.disabled import org.jetbrains.compose.web.attributes.AttrsScope +import org.jetbrains.compose.web.attributes.AutoComplete +import org.jetbrains.compose.web.attributes.InputType /** * @see AttrsScope.attr @@ -9,11 +11,23 @@ import org.jetbrains.compose.web.attributes.AttrsScope fun AttrsScope<*>.attr(attr: String, isPresent: Boolean = true) = attr(attr, isPresent.toString()) +/** + * [Int] attributes are used in Compose HTML. See [org.jetbrains.compose.web.attributes.maxLength] for example. + */ +fun AttrsScope<*>.attr(attr: String, number: Int) = + attr(attr, number.toString()) + // https://www.w3schools.com/accessibility/accessibility_labels.php // https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label fun AttrsScope<*>.ariaLabel(value: String) = attr("aria-label", value) +// https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/slot +fun AttrsScope<*>.slot(value: String) = + attr("slot", value) + +// Consider moving what's below to a `InputAttrs.kt` file in a `compose-html-material-common` module and depend on them with `implementation`. + // https://www.w3schools.com/tags/att_disabled.asp // https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/disabled fun AttrsScope<*>.disabled(disabled: Boolean?) { @@ -43,18 +57,80 @@ fun AttrsScope<*>.value(value: String?) { value?.let { attr("value", it) } } -// https://www.w3schools.com/tags/att_form.asp -fun AttrsScope<*>.form(formId: String?) { - formId?.let { attr("form", it) } -} - // https://www.w3schools.com/tags/att_name.asp fun AttrsScope<*>.name(name: String?) { name?.let { attr("name", it) } } +// https://www.w3schools.com/tags/att_form.asp +fun AttrsScope<*>.form(formId: String?) { + formId?.let { attr("form", it) } +} + // https://www.w3schools.com/tags/att_required.asp // https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/required fun AttrsScope<*>.required(required: Boolean?) { required?.let { attr("required", it) } } + +fun AttrsScope<*>.label(label: String?) { + label?.let { attr("label", it) } +} + +// copied and adapted from `Attrs.kt` in `org.jetbrains.compose.web.attributes` + +// https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#max +fun AttrsScope<*>.max(value: String?) { + value?.let { attr("max", it) } +} + +// https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#maxlength +fun AttrsScope<*>.maxLength(value: Int?) { + value?.let { attr("maxlength", it) } +} + +// https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#min +fun AttrsScope<*>.min(value: String?) { + value?.let { attr("min", it) } +} + +// https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#minlength +fun AttrsScope<*>.minLength(value: Int?) { + value?.let { attr("minlength", it) } +} + +// https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#pattern +fun AttrsScope<*>.pattern(value: String?) { + value?.let { attr("pattern", it) } +} + +// https://www.w3schools.com/tags/att_input_placeholder.asp +// https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/placeholder +fun AttrsScope<*>.placeholder(value: String?) { + value?.let { attr("placeholder", it) } +} + +// https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#readonly +fun AttrsScope<*>.readOnly(value: Boolean?) { + value?.let { attr("readonly", it) } +} + +// https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/email#multiple +fun AttrsScope<*>.multiple(value: Boolean?) { + value?.let { attr("multiple", it) } +} + +// https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#step +fun AttrsScope<*>.step(value: String?) { + value?.let { attr("step", it) } +} + +// https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#input_types +fun AttrsScope<*>.type(value: InputType<*>?) { + value?.let { attr("type", it.typeStr) } +} + +// https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/autocomplete +fun AttrsScope<*>.autoComplete(value: AutoComplete?) { + value?.let { attr("autocomplete", value.unsafeCast()) } +} diff --git a/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/EventAttrs.kt b/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/EventAttrs.kt new file mode 100644 index 0000000..266dc11 --- /dev/null +++ b/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/EventAttrs.kt @@ -0,0 +1,15 @@ +package com.huanshankeji.compose.web.attributes + +import androidx.compose.web.events.SyntheticEvent +import org.jetbrains.compose.web.attributes.AttrsScope +import org.jetbrains.compose.web.attributes.EventsListenerScope +import org.w3c.dom.HTMLElement + +/** + * @see com.huanshankeji.compose.web.dom.value + */ +//fun EventsListenerScope.onInput( +fun AttrsScope.onInput( + listener: (SyntheticEvent) -> Unit +) = + addEventListener(EventsListenerScope.INPUT, listener) diff --git a/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/EventsListenerScope.kt b/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/EventsListenerScope.kt deleted file mode 100644 index 893cc6d..0000000 --- a/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/EventsListenerScope.kt +++ /dev/null @@ -1,10 +0,0 @@ -package com.huanshankeji.compose.web.attributes - -import androidx.compose.web.events.SyntheticEvent -import org.jetbrains.compose.web.attributes.EventsListenerScope -import org.w3c.dom.events.EventTarget - -fun EventsListenerScope.onInput( - listener: (SyntheticEvent) -> Unit -) = - addEventListener(EventsListenerScope.INPUT, listener) diff --git a/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/dom/dom.kt b/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/dom/dom.kt new file mode 100644 index 0000000..1683cb9 --- /dev/null +++ b/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/dom/dom.kt @@ -0,0 +1,9 @@ +package com.huanshankeji.compose.web.dom + +import org.w3c.dom.HTMLElement + +/** + * @see com.huanshankeji.compose.web.attributes.onInput + */ +val HTMLElement.value: String + get() = asDynamic().value as String diff --git a/compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MdButton.kt b/compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MdButton.kt index aefeaaa..4070583 100644 --- a/compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MdButton.kt +++ b/compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MdButton.kt @@ -6,6 +6,7 @@ import org.jetbrains.compose.web.attributes.AttrsScope import org.jetbrains.compose.web.dom.ElementScope import org.jetbrains.compose.web.dom.TagElement import org.w3c.dom.HTMLElement + /* https://github.com/material-components/material-web/blob/main/docs/components/button.md https://material-web.dev/components/button/ @@ -42,6 +43,7 @@ private fun commonButtonAttrs( value(value) name(name) form(form) + attrs?.invoke(this) } @@ -198,6 +200,6 @@ fun MdTextButton( class MdButtonScope(val elementScope: ElementScope) { - fun AttrsScope<*>.slotIcon() = + fun AttrsScope<*>.slotEqIcon() = attr("slot", "icon") } diff --git a/compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MdCheckbox.kt b/compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MdCheckbox.kt index 5f4ce2e..fdebf33 100644 --- a/compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MdCheckbox.kt +++ b/compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MdCheckbox.kt @@ -17,11 +17,8 @@ fun MdCheckbox( indeterminate: Boolean? = null, required: Boolean? = null, value: String? = null, + name: String? = null, form: String? = null, - //labels : NodeList? = null, // This is a read-only property. See https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement/labels. - //validity : ValidityState? = null, // This is a read-only property. See https://developer.mozilla.org/en-US/docs/Web/API/HTMLObjectElement/validity. - //validationMessage : String? = null, // This is a read-only property. See https://developer.mozilla.org/en-US/docs/Web/API/HTMLObjectElement/validationMessage. - //willValidate : Boolean? = null, // This is a read-only property. See https://developer.mozilla.org/en-US/docs/Web/API/HTMLObjectElement/willValidate. attrs: Attrs? = null ) { require("@material/web/checkbox/checkbox.js") @@ -33,7 +30,9 @@ fun MdCheckbox( indeterminate?.let { attr("indeterminate", it) } required(required) value(value) + name(name) form(form) + attrs?.invoke(this) }, null) } @@ -49,6 +48,7 @@ fun MdCheckbox( disabled: Boolean? = null, required: Boolean? = null, value: String? = null, + name: String? = null, form: String? = null, attrs: Attrs? = null ) { @@ -71,5 +71,5 @@ fun MdCheckbox( } } - MdCheckbox(checked, disabled, indeterminate, required, value, form, attrs) + MdCheckbox(checked, disabled, indeterminate, required, value, name, form, attrs) } diff --git a/compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MdSwitch.kt b/compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MdSwitch.kt index 53d9593..9b12da3 100644 --- a/compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MdSwitch.kt +++ b/compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MdSwitch.kt @@ -30,11 +30,12 @@ fun MdSwitch( disabled(disabled) selected?.let { attr("selected", it) } icons?.let { attr("icons", it) } - showOnlySelectedIcon?.let { attr("showOnlySelectedIcon", it) } + showOnlySelectedIcon?.let { attr("show-only-selected-icon", it) } required(required) value(value) name(name) form(form) + attrs?.invoke(this) }, null) } diff --git a/compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MdTextField.kt b/compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MdTextField.kt new file mode 100644 index 0000000..58c1cf3 --- /dev/null +++ b/compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MdTextField.kt @@ -0,0 +1,222 @@ +package com.huanshankeji.compose.html.material3 + +import androidx.compose.runtime.Composable +import com.huanshankeji.compose.web.attributes.* +import org.jetbrains.compose.web.attributes.AttrsScope +import org.jetbrains.compose.web.attributes.AutoComplete +import org.jetbrains.compose.web.attributes.InputMode +import org.jetbrains.compose.web.attributes.InputType +import org.jetbrains.compose.web.dom.ElementScope +import org.jetbrains.compose.web.dom.TagElement +import org.w3c.dom.HTMLElement + +/* +https://github.com/material-components/material-web/blob/main/docs/components/text-field.md +https://material-web.dev/components/text-field/ +https://material-web.dev/components/text-field/stories/ +*/ + +@Composable +private fun CommonTextField( + tagName: String, + disabled: Boolean?, + error: Boolean?, + errorText: String?, + label: String?, + required: Boolean?, + value: String?, + prefixText: String?, + suffixText: String?, + hasLeadingIcon: Boolean?, + hasTrailingIcon: Boolean?, + supportingText: String?, + textDirection: String?, + rows: Int?, // The JavaScript `number` is actually a `Double`. See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number. + cols: Int?, + inputMode: InputMode?, + max: String?, + maxLength: Int?, + min: String?, + minLength: Int?, + pattern: String?, + placeholder: String?, + readOnly: Boolean?, + multiple: Boolean?, + step: String?, + type: InputType<*>?, + autocomplete: AutoComplete?, + attrs: Attrs?, + content: (@Composable MdTextFieldScope.() -> Unit)? +) = + TagElement(tagName, { + disabled(disabled) + error?.let { attr("error", it) } + errorText?.let { attr("error-text", it) } + label(label) + required(required) + value(value) + prefixText?.let { attr("prefix-text", it) } + suffixText?.let { attr("suffix-text", it) } + hasLeadingIcon?.let { attr("has-leading-icon", it) } + hasTrailingIcon?.let { attr("has-trailing-icon", it) } + supportingText?.let { attr("supporting-text", it) } + textDirection?.let { attr("text-direction", it) } + rows?.let { attr("rows", it) } + cols?.let { attr("cols", it) } + inputMode?.let { inputMode(it) } + max(max) + maxLength(maxLength) + min(min) + minLength(minLength) + pattern(pattern) + placeholder(placeholder) + readOnly(readOnly) + multiple(multiple) + step(step) + type(type) + autoComplete(autocomplete) + + attrs?.invoke(this) + }, content?.let { { MdTextFieldScope(this).it() } }) + +@Composable +fun MdFilledTextField( + disabled: Boolean? = null, + error: Boolean? = null, + errorText: String? = null, + label: String? = null, + required: Boolean? = null, + value: String? = null, + prefixText: String? = null, + suffixText: String? = null, + hasLeadingIcon: Boolean? = null, + hasTrailingIcon: Boolean? = null, + supportingText: String? = null, + textDirection: String? = null, + rows: Int? = null, + cols: Int? = null, + inputMode: InputMode? = null, + max: String? = null, + maxLength: Int? = null, + min: String? = null, + minLength: Int? = null, + pattern: String? = null, + placeholder: String? = null, + readOnly: Boolean? = null, + multiple: Boolean? = null, + step: String? = null, + type: InputType<*>? = null, + autocomplete: AutoComplete? = null, + attrs: Attrs? = null, + content: (@Composable MdTextFieldScope.() -> Unit)? = null +) { + require("@material/web/textfield/filled-text-field.js") + + CommonTextField( + "md-filled-text-field", + disabled, + error, + errorText, + label, + required, + value, + prefixText, + suffixText, + hasLeadingIcon, + hasTrailingIcon, + supportingText, + textDirection, + rows, + cols, + inputMode, + max, + maxLength, + min, + minLength, + pattern, + placeholder, + readOnly, + multiple, + step, + type, + autocomplete, + attrs, + content + ) +} + +@Composable +fun MdOutlinedTextField( + disabled: Boolean? = null, + error: Boolean? = null, + errorText: String? = null, + label: String? = null, + required: Boolean? = null, + value: String? = null, + prefixText: String? = null, + suffixText: String? = null, + hasLeadingIcon: Boolean? = null, + hasTrailingIcon: Boolean? = null, + supportingText: String? = null, + textDirection: String? = null, + rows: Int? = null, + cols: Int? = null, + inputMode: InputMode? = null, + max: String? = null, + maxLength: Int? = null, + min: String? = null, + minLength: Int? = null, + pattern: String? = null, + placeholder: String? = null, + readOnly: Boolean? = null, + multiple: Boolean? = null, + step: String? = null, + type: InputType<*>? = null, + autocomplete: AutoComplete? = null, + attrs: Attrs? = null, + content: (@Composable MdTextFieldScope.() -> Unit)? = null +) { + require("@material/web/textfield/outlined-text-field.js") + + CommonTextField( + "md-outlined-text-field", + disabled, + error, + errorText, + label, + required, + value, + prefixText, + suffixText, + hasLeadingIcon, + hasTrailingIcon, + supportingText, + textDirection, + rows, + cols, + inputMode, + max, + maxLength, + min, + minLength, + pattern, + placeholder, + readOnly, + multiple, + step, + type, + autocomplete, + attrs, + content + ) +} + + +class MdTextFieldScope(val elementScope: ElementScope) { + enum class Slot(val value: String) { + LeadingIcon("leading-icon"), TrailingIcon("trailing-icon") + } + + fun AttrsScope<*>.slot(value: Slot) = + slot(value.value) +} From 1923360f11f5a71ba15e8fcede461607ced18e97 Mon Sep 17 00:00:00 2001 From: Shreck Ye Date: Mon, 29 Apr 2024 03:34:40 +0800 Subject: [PATCH 18/34] Move some attributes and extensions to the `ext` packages, see the first comment in `Attrs.kt` in `com.huanshankeji.compose.web.attributes.ext` for more details --- .../compose/web/attributes/Attrs.kt | 114 ---------------- .../compose/web/attributes/ext/Attrs.kt | 128 ++++++++++++++++++ .../web/attributes/{ => ext}/EventAttrs.kt | 2 +- .../compose/web/dom/{ => ext}/dom.kt | 2 +- .../compose/html/material3/MdButton.kt | 3 +- .../compose/html/material3/MdCheckbox.kt | 4 +- .../compose/html/material3/MdSwitch.kt | 4 +- .../compose/html/material3/MdTextField.kt | 7 +- 8 files changed, 143 insertions(+), 121 deletions(-) create mode 100644 compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/ext/Attrs.kt rename compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/{ => ext}/EventAttrs.kt (90%) rename compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/dom/{ => ext}/dom.kt (78%) diff --git a/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/Attrs.kt b/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/Attrs.kt index 6a074c7..ba38843 100644 --- a/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/Attrs.kt +++ b/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/Attrs.kt @@ -17,120 +17,6 @@ fun AttrsScope<*>.attr(attr: String, isPresent: Boolean = true) = fun AttrsScope<*>.attr(attr: String, number: Int) = attr(attr, number.toString()) -// https://www.w3schools.com/accessibility/accessibility_labels.php -// https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label -fun AttrsScope<*>.ariaLabel(value: String) = - attr("aria-label", value) - // https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/slot fun AttrsScope<*>.slot(value: String) = attr("slot", value) - -// Consider moving what's below to a `InputAttrs.kt` file in a `compose-html-material-common` module and depend on them with `implementation`. - -// https://www.w3schools.com/tags/att_disabled.asp -// https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/disabled -fun AttrsScope<*>.disabled(disabled: Boolean?) { - disabled?.let { disabled(it) } -} - -// https://www.w3schools.com/tags/att_href.asp -// https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a#href -fun AttrsScope<*>.href(href: String?) { - href?.let { attr("href", it) } -} - -// https://www.w3schools.com/tags/att_target.asp -// https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a#target -fun AttrsScope<*>.target(target: String?) { - target?.let { attr("target", it) } -} - -// https://www.w3schools.com/tags/att_input_type.asp -// https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#type -fun AttrsScope<*>.type(type: String?) { - type?.let { attr("type", it) } -} - -// https://www.w3schools.com/tags/att_value.asp -fun AttrsScope<*>.value(value: String?) { - value?.let { attr("value", it) } -} - -// https://www.w3schools.com/tags/att_name.asp -fun AttrsScope<*>.name(name: String?) { - name?.let { attr("name", it) } -} - -// https://www.w3schools.com/tags/att_form.asp -fun AttrsScope<*>.form(formId: String?) { - formId?.let { attr("form", it) } -} - -// https://www.w3schools.com/tags/att_required.asp -// https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/required -fun AttrsScope<*>.required(required: Boolean?) { - required?.let { attr("required", it) } -} - -fun AttrsScope<*>.label(label: String?) { - label?.let { attr("label", it) } -} - -// copied and adapted from `Attrs.kt` in `org.jetbrains.compose.web.attributes` - -// https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#max -fun AttrsScope<*>.max(value: String?) { - value?.let { attr("max", it) } -} - -// https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#maxlength -fun AttrsScope<*>.maxLength(value: Int?) { - value?.let { attr("maxlength", it) } -} - -// https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#min -fun AttrsScope<*>.min(value: String?) { - value?.let { attr("min", it) } -} - -// https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#minlength -fun AttrsScope<*>.minLength(value: Int?) { - value?.let { attr("minlength", it) } -} - -// https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#pattern -fun AttrsScope<*>.pattern(value: String?) { - value?.let { attr("pattern", it) } -} - -// https://www.w3schools.com/tags/att_input_placeholder.asp -// https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/placeholder -fun AttrsScope<*>.placeholder(value: String?) { - value?.let { attr("placeholder", it) } -} - -// https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#readonly -fun AttrsScope<*>.readOnly(value: Boolean?) { - value?.let { attr("readonly", it) } -} - -// https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/email#multiple -fun AttrsScope<*>.multiple(value: Boolean?) { - value?.let { attr("multiple", it) } -} - -// https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#step -fun AttrsScope<*>.step(value: String?) { - value?.let { attr("step", it) } -} - -// https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#input_types -fun AttrsScope<*>.type(value: InputType<*>?) { - value?.let { attr("type", it.typeStr) } -} - -// https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/autocomplete -fun AttrsScope<*>.autoComplete(value: AutoComplete?) { - value?.let { attr("autocomplete", value.unsafeCast()) } -} diff --git a/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/ext/Attrs.kt b/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/ext/Attrs.kt new file mode 100644 index 0000000..fcb5ac5 --- /dev/null +++ b/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/ext/Attrs.kt @@ -0,0 +1,128 @@ +package com.huanshankeji.compose.web.attributes.ext + +import com.huanshankeji.compose.web.attributes.attr +import com.varabyte.kobweb.compose.css.disabled +import org.jetbrains.compose.web.attributes.AttrsScope +import org.jetbrains.compose.web.attributes.AutoComplete +import org.jetbrains.compose.web.attributes.InputType + +/* +Attributes in this package are for `HTMLElement`s which don't implement the interfaces (such as `HTMLInputElement`) of the elements they behave like, +such as the `HTMLElement`s of those components in Material Web. +These attributes should not be universally available on most elements. + */ + + +// https://www.w3schools.com/accessibility/accessibility_labels.php +// https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label +fun AttrsScope<*>.ariaLabel(value: String) = + attr("aria-label", value) + +// Consider moving what's below to a `InputAttrs.kt` file in a `compose-html-material-common` module and depend on them with `implementation`. + +// https://www.w3schools.com/tags/att_disabled.asp +// https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/disabled +fun AttrsScope<*>.disabled(disabled: Boolean?) { + disabled?.let { disabled(it) } +} + +// https://www.w3schools.com/tags/att_href.asp +// https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a#href +fun AttrsScope<*>.href(href: String?) { + href?.let { attr("href", it) } +} + +// https://www.w3schools.com/tags/att_target.asp +// https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a#target +fun AttrsScope<*>.target(target: String?) { + target?.let { attr("target", it) } +} + +// https://www.w3schools.com/tags/att_input_type.asp +// https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#type +fun AttrsScope<*>.type(type: String?) { + type?.let { attr("type", it) } +} + +// https://www.w3schools.com/tags/att_value.asp +fun AttrsScope<*>.value(value: String?) { + value?.let { attr("value", it) } +} + +// https://www.w3schools.com/tags/att_name.asp +fun AttrsScope<*>.name(name: String?) { + name?.let { attr("name", it) } +} + +// https://www.w3schools.com/tags/att_form.asp +fun AttrsScope<*>.form(formId: String?) { + formId?.let { attr("form", it) } +} + +// https://www.w3schools.com/tags/att_required.asp +// https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/required +fun AttrsScope<*>.required(required: Boolean?) { + required?.let { attr("required", it) } +} +// https://www.geeksforgeeks.org/html-label-attribute/ +fun AttrsScope<*>.label(label: String?) { + label?.let { attr("label", it) } +} + +// copied and adapted from `Attrs.kt` in `org.jetbrains.compose.web.attributes` + +// https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#max +fun AttrsScope<*>.max(value: String?) { + value?.let { attr("max", it) } +} + +// https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#maxlength +fun AttrsScope<*>.maxLength(value: Int?) { + value?.let { attr("maxlength", it) } +} + +// https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#min +fun AttrsScope<*>.min(value: String?) { + value?.let { attr("min", it) } +} + +// https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#minlength +fun AttrsScope<*>.minLength(value: Int?) { + value?.let { attr("minlength", it) } +} + +// https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#pattern +fun AttrsScope<*>.pattern(value: String?) { + value?.let { attr("pattern", it) } +} + +// https://www.w3schools.com/tags/att_input_placeholder.asp +// https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/placeholder +fun AttrsScope<*>.placeholder(value: String?) { + value?.let { attr("placeholder", it) } +} + +// https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#readonly +fun AttrsScope<*>.readOnly(value: Boolean?) { + value?.let { attr("readonly", it) } +} + +// https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/email#multiple +fun AttrsScope<*>.multiple(value: Boolean?) { + value?.let { attr("multiple", it) } +} + +// https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#step +fun AttrsScope<*>.step(value: String?) { + value?.let { attr("step", it) } +} + +// https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#input_types +fun AttrsScope<*>.type(value: InputType<*>?) { + value?.let { attr("type", it.typeStr) } +} + +// https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/autocomplete +fun AttrsScope<*>.autoComplete(value: AutoComplete?) { + value?.let { attr("autocomplete", value.unsafeCast()) } +} diff --git a/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/EventAttrs.kt b/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/ext/EventAttrs.kt similarity index 90% rename from compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/EventAttrs.kt rename to compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/ext/EventAttrs.kt index 266dc11..26b43d1 100644 --- a/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/EventAttrs.kt +++ b/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/ext/EventAttrs.kt @@ -1,4 +1,4 @@ -package com.huanshankeji.compose.web.attributes +package com.huanshankeji.compose.web.attributes.ext import androidx.compose.web.events.SyntheticEvent import org.jetbrains.compose.web.attributes.AttrsScope diff --git a/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/dom/dom.kt b/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/dom/ext/dom.kt similarity index 78% rename from compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/dom/dom.kt rename to compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/dom/ext/dom.kt index 1683cb9..d699c6f 100644 --- a/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/dom/dom.kt +++ b/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/dom/ext/dom.kt @@ -1,4 +1,4 @@ -package com.huanshankeji.compose.web.dom +package com.huanshankeji.compose.web.dom.ext import org.w3c.dom.HTMLElement diff --git a/compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MdButton.kt b/compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MdButton.kt index 4070583..19901b1 100644 --- a/compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MdButton.kt +++ b/compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MdButton.kt @@ -1,7 +1,8 @@ package com.huanshankeji.compose.html.material3 import androidx.compose.runtime.Composable -import com.huanshankeji.compose.web.attributes.* +import com.huanshankeji.compose.web.attributes.Attrs +import com.huanshankeji.compose.web.attributes.ext.* import org.jetbrains.compose.web.attributes.AttrsScope import org.jetbrains.compose.web.dom.ElementScope import org.jetbrains.compose.web.dom.TagElement diff --git a/compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MdCheckbox.kt b/compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MdCheckbox.kt index fdebf33..7d76f32 100644 --- a/compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MdCheckbox.kt +++ b/compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MdCheckbox.kt @@ -1,7 +1,9 @@ package com.huanshankeji.compose.html.material3 import androidx.compose.runtime.Composable -import com.huanshankeji.compose.web.attributes.* +import com.huanshankeji.compose.web.attributes.Attrs +import com.huanshankeji.compose.web.attributes.attr +import com.huanshankeji.compose.web.attributes.ext.* import org.jetbrains.compose.web.dom.TagElement import org.w3c.dom.HTMLElement diff --git a/compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MdSwitch.kt b/compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MdSwitch.kt index 9b12da3..b80ed60 100644 --- a/compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MdSwitch.kt +++ b/compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MdSwitch.kt @@ -1,7 +1,9 @@ package com.huanshankeji.compose.html.material3 import androidx.compose.runtime.Composable -import com.huanshankeji.compose.web.attributes.* +import com.huanshankeji.compose.web.attributes.Attrs +import com.huanshankeji.compose.web.attributes.attr +import com.huanshankeji.compose.web.attributes.ext.* import org.jetbrains.compose.web.dom.Label import org.jetbrains.compose.web.dom.TagElement import org.jetbrains.compose.web.dom.Text diff --git a/compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MdTextField.kt b/compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MdTextField.kt index 58c1cf3..0a397e5 100644 --- a/compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MdTextField.kt +++ b/compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MdTextField.kt @@ -1,7 +1,10 @@ package com.huanshankeji.compose.html.material3 import androidx.compose.runtime.Composable -import com.huanshankeji.compose.web.attributes.* +import com.huanshankeji.compose.web.attributes.Attrs +import com.huanshankeji.compose.web.attributes.attr +import com.huanshankeji.compose.web.attributes.ext.* +import com.huanshankeji.compose.web.attributes.slot import org.jetbrains.compose.web.attributes.AttrsScope import org.jetbrains.compose.web.attributes.AutoComplete import org.jetbrains.compose.web.attributes.InputMode @@ -22,7 +25,7 @@ private fun CommonTextField( disabled: Boolean?, error: Boolean?, errorText: String?, - label: String?, + label: String?, // This attribute seems to have different semantics here from its original semantics in HTML. required: Boolean?, value: String?, prefixText: String?, From 4b6af9b4ced12a1469051d221858f517782049fd Mon Sep 17 00:00:00 2001 From: Shreck Ye Date: Mon, 29 Apr 2024 03:36:43 +0800 Subject: [PATCH 19/34] Update a comment --- .../kotlin/com/huanshankeji/compose/web/attributes/ext/Attrs.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/ext/Attrs.kt b/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/ext/Attrs.kt index fcb5ac5..c5cd044 100644 --- a/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/ext/Attrs.kt +++ b/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/ext/Attrs.kt @@ -10,6 +10,7 @@ import org.jetbrains.compose.web.attributes.InputType Attributes in this package are for `HTMLElement`s which don't implement the interfaces (such as `HTMLInputElement`) of the elements they behave like, such as the `HTMLElement`s of those components in Material Web. These attributes should not be universally available on most elements. +Also consider moving to a `compose-html-material-common` module and depend on them with `implementation`. */ @@ -18,7 +19,6 @@ These attributes should not be universally available on most elements. fun AttrsScope<*>.ariaLabel(value: String) = attr("aria-label", value) -// Consider moving what's below to a `InputAttrs.kt` file in a `compose-html-material-common` module and depend on them with `implementation`. // https://www.w3schools.com/tags/att_disabled.asp // https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/disabled From 30a6b8593d54de667baad5bf943847ea558581b7 Mon Sep 17 00:00:00 2001 From: Shreck Ye Date: Mon, 29 Apr 2024 04:04:35 +0800 Subject: [PATCH 20/34] Introduce the new `attrIfNotNull` extension functions and adapt the existing attribute extensions to use them, and rename all the attribute value parameters to `value` for consistency --- .../compose/web/attributes/Attrs.kt | 25 +++-- .../compose/web/attributes/ext/Attrs.kt | 100 ++++++++---------- 2 files changed, 63 insertions(+), 62 deletions(-) diff --git a/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/Attrs.kt b/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/Attrs.kt index ba38843..a79474b 100644 --- a/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/Attrs.kt +++ b/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/Attrs.kt @@ -1,21 +1,32 @@ package com.huanshankeji.compose.web.attributes -import com.varabyte.kobweb.compose.css.disabled import org.jetbrains.compose.web.attributes.AttrsScope -import org.jetbrains.compose.web.attributes.AutoComplete -import org.jetbrains.compose.web.attributes.InputType /** * @see AttrsScope.attr */ -fun AttrsScope<*>.attr(attr: String, isPresent: Boolean = true) = - attr(attr, isPresent.toString()) +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, number: Int) = - attr(attr, number.toString()) +fun AttrsScope<*>.attr(attr: String, value: Int) = + attr(attr, value.toString()) + + +fun AttrsScope<*>.attrIfNotNull(attr: String, value: String?) { + value?.let { attr(attr, it) } +} + +fun AttrsScope<*>.attrIfNotNull(attr: String, isPresent: Boolean?) { + isPresent?.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) = diff --git a/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/ext/Attrs.kt b/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/ext/Attrs.kt index c5cd044..53205d4 100644 --- a/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/ext/Attrs.kt +++ b/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/ext/Attrs.kt @@ -1,15 +1,17 @@ package com.huanshankeji.compose.web.attributes.ext -import com.huanshankeji.compose.web.attributes.attr -import com.varabyte.kobweb.compose.css.disabled +import com.huanshankeji.compose.web.attributes.attrIfNotNull import org.jetbrains.compose.web.attributes.AttrsScope import org.jetbrains.compose.web.attributes.AutoComplete import org.jetbrains.compose.web.attributes.InputType /* -Attributes in this package are for `HTMLElement`s which don't implement the interfaces (such as `HTMLInputElement`) of the elements they behave like, +Attributes in the `ext` package are one of 2 kinds: +1. Those for `HTMLElement`s which don't implement the interfaces (such as `HTMLInputElement`) of the elements they behave like, such as the `HTMLElement`s of those components in Material Web. These attributes should not be universally available on most elements. +1. Those taking nullable values. + Also consider moving to a `compose-html-material-common` module and depend on them with `implementation`. */ @@ -28,94 +30,82 @@ fun AttrsScope<*>.disabled(disabled: Boolean?) { // https://www.w3schools.com/tags/att_href.asp // https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a#href -fun AttrsScope<*>.href(href: String?) { - href?.let { attr("href", it) } -} +fun AttrsScope<*>.href(value: String?) = + attrIfNotNull("href", value) // https://www.w3schools.com/tags/att_target.asp // https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a#target -fun AttrsScope<*>.target(target: String?) { - target?.let { attr("target", it) } -} +fun AttrsScope<*>.target(value: String?) = + attrIfNotNull("target", value) + // https://www.w3schools.com/tags/att_input_type.asp // https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#type -fun AttrsScope<*>.type(type: String?) { - type?.let { attr("type", it) } -} +fun AttrsScope<*>.type(value: String?) = + attrIfNotNull("type", value) // https://www.w3schools.com/tags/att_value.asp -fun AttrsScope<*>.value(value: String?) { - value?.let { attr("value", it) } -} +fun AttrsScope<*>.value(value: String?) = + attrIfNotNull("value", value) + // https://www.w3schools.com/tags/att_name.asp -fun AttrsScope<*>.name(name: String?) { - name?.let { attr("name", it) } -} +fun AttrsScope<*>.name(value: String?) = + attrIfNotNull("name", value) + // https://www.w3schools.com/tags/att_form.asp -fun AttrsScope<*>.form(formId: String?) { - formId?.let { attr("form", it) } -} +fun AttrsScope<*>.form(value: String?) = + attrIfNotNull("form", value) // https://www.w3schools.com/tags/att_required.asp // https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/required -fun AttrsScope<*>.required(required: Boolean?) { - required?.let { attr("required", it) } -} +fun AttrsScope<*>.required(value: Boolean?) = + attrIfNotNull("required", value) + // https://www.geeksforgeeks.org/html-label-attribute/ -fun AttrsScope<*>.label(label: String?) { - label?.let { attr("label", it) } -} +fun AttrsScope<*>.label(value: String?) = + attrIfNotNull("label", value) // copied and adapted from `Attrs.kt` in `org.jetbrains.compose.web.attributes` // https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#max -fun AttrsScope<*>.max(value: String?) { - value?.let { attr("max", it) } -} +fun AttrsScope<*>.max(value: String?) = + attrIfNotNull("max", value) // https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#maxlength -fun AttrsScope<*>.maxLength(value: Int?) { - value?.let { attr("maxlength", it) } -} +fun AttrsScope<*>.maxLength(value: Int?) = + attrIfNotNull("maxlength", value) // https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#min -fun AttrsScope<*>.min(value: String?) { - value?.let { attr("min", it) } -} +fun AttrsScope<*>.min(value: String?) = + attrIfNotNull("min", value) // https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#minlength -fun AttrsScope<*>.minLength(value: Int?) { - value?.let { attr("minlength", it) } -} +fun AttrsScope<*>.minLength(value: Int?) = + attrIfNotNull("minlength", value) // https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#pattern -fun AttrsScope<*>.pattern(value: String?) { - value?.let { attr("pattern", it) } -} +fun AttrsScope<*>.pattern(value: String?) = + attrIfNotNull("pattern", value) // https://www.w3schools.com/tags/att_input_placeholder.asp // https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/placeholder -fun AttrsScope<*>.placeholder(value: String?) { - value?.let { attr("placeholder", it) } -} +fun AttrsScope<*>.placeholder(value: String?) = + attrIfNotNull("placeholder", value) // https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#readonly -fun AttrsScope<*>.readOnly(value: Boolean?) { - value?.let { attr("readonly", it) } -} +fun AttrsScope<*>.readOnly(value: Boolean?) = + attrIfNotNull("readonly", value) + // https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/email#multiple -fun AttrsScope<*>.multiple(value: Boolean?) { - value?.let { attr("multiple", it) } -} +fun AttrsScope<*>.multiple(value: Boolean?) = + attrIfNotNull("multiple", value) // https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#step -fun AttrsScope<*>.step(value: String?) { - value?.let { attr("step", it) } -} +fun AttrsScope<*>.step(value: String?) = + attrIfNotNull("step", value) // https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#input_types fun AttrsScope<*>.type(value: InputType<*>?) { @@ -124,5 +114,5 @@ fun AttrsScope<*>.type(value: InputType<*>?) { // https://developer.mozilla.org/en-US/docs/Web/HTML/Attributes/autocomplete fun AttrsScope<*>.autoComplete(value: AutoComplete?) { - value?.let { attr("autocomplete", value.unsafeCast()) } + value?.let { attr("autocomplete", it.unsafeCast()) } } From c94ff8b6098d48c95748835b8a60605458fe8333 Mon Sep 17 00:00:00 2001 From: Shreck Ye Date: Mon, 29 Apr 2024 04:06:57 +0800 Subject: [PATCH 21/34] Add a comment --- .../kotlin/com/huanshankeji/compose/web/attributes/ext/Attrs.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/ext/Attrs.kt b/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/ext/Attrs.kt index 53205d4..7196ffe 100644 --- a/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/ext/Attrs.kt +++ b/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/ext/Attrs.kt @@ -13,6 +13,7 @@ These attributes should not be universally available on most elements. 1. Those taking nullable values. Also consider moving to a `compose-html-material-common` module and depend on them with `implementation`. +Consider reordering them. */ From 8278613922a17a5b6a6199121b768604710e3785 Mon Sep 17 00:00:00 2001 From: Shreck Ye Date: Tue, 30 Apr 2024 02:42:49 +0800 Subject: [PATCH 22/34] Add some new attributes for some new functionalities in "compose-multiplatform-material" Fix some broken references caused by commit 1923360f11f5a71ba15e8fcede461607ced18e97 BTW. --- .../compose/web/attributes/AttrConversion.kt | 5 +- .../compose/web/attributes/Attrs.kt | 49 +++++++++++++++++++ .../compose/web/attributes/ext/Attrs.kt | 20 ++++++++ .../compose/web/attributes/ext/EventAttrs.kt | 2 +- .../huanshankeji/compose/web/dom/ext/dom.kt | 2 +- 5 files changed, 75 insertions(+), 3 deletions(-) diff --git a/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/AttrConversion.kt b/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/AttrConversion.kt index b7cdf4f..37202a1 100644 --- a/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/AttrConversion.kt +++ b/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/AttrConversion.kt @@ -2,8 +2,11 @@ package com.huanshankeji.compose.web.attributes // consider moving to a "web-common" or "html-common" module -fun Boolean.isTrueOrNull() : Boolean? = +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" diff --git a/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/Attrs.kt b/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/Attrs.kt index a79474b..97360e9 100644 --- a/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/Attrs.kt +++ b/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/Attrs.kt @@ -3,6 +3,7 @@ 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) = @@ -14,6 +15,12 @@ fun AttrsScope<*>.attr(attr: String, value: Boolean = true) = 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) } @@ -31,3 +38,45 @@ fun AttrsScope<*>.attrIfNotNull(attr: String, value: Int?) { // 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) diff --git a/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/ext/Attrs.kt b/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/ext/Attrs.kt index 7196ffe..c023d38 100644 --- a/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/ext/Attrs.kt +++ b/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/ext/Attrs.kt @@ -1,6 +1,10 @@ package com.huanshankeji.compose.web.attributes.ext +import com.huanshankeji.compose.web.attributes.AutoCapitalize +import com.huanshankeji.compose.web.attributes.EnterKeyHint import com.huanshankeji.compose.web.attributes.attrIfNotNull +import com.huanshankeji.compose.web.attributes.autoCapitalize +import com.huanshankeji.compose.web.attributes.enterKeyHint import org.jetbrains.compose.web.attributes.AttrsScope import org.jetbrains.compose.web.attributes.AutoComplete import org.jetbrains.compose.web.attributes.InputType @@ -117,3 +121,19 @@ fun AttrsScope<*>.type(value: InputType<*>?) { fun AttrsScope<*>.autoComplete(value: AutoComplete?) { value?.let { attr("autocomplete", it.unsafeCast()) } } + + +// This is actually a global attribute +// https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/autocapitalize +fun AttrsScope<*>.autoCapitalize(value: String?) = + value?.let { this@autoCapitalize.autoCapitalize(value) } + +fun AttrsScope<*>.autoCapitalizeRequiringValid(value: String) { + require(value in AutoCapitalize.valueSet) + autoCapitalize(value) +} + + +fun AttrsScope<*>.enterKeyHintIfValid(value: String) { + if (value in EnterKeyHint.valueSet) enterKeyHint(value) +} diff --git a/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/ext/EventAttrs.kt b/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/ext/EventAttrs.kt index 26b43d1..c620012 100644 --- a/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/ext/EventAttrs.kt +++ b/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/ext/EventAttrs.kt @@ -6,7 +6,7 @@ import org.jetbrains.compose.web.attributes.EventsListenerScope import org.w3c.dom.HTMLElement /** - * @see com.huanshankeji.compose.web.dom.value + * @see com.huanshankeji.compose.web.dom.ext.value */ //fun EventsListenerScope.onInput( fun AttrsScope.onInput( diff --git a/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/dom/ext/dom.kt b/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/dom/ext/dom.kt index d699c6f..f676732 100644 --- a/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/dom/ext/dom.kt +++ b/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/dom/ext/dom.kt @@ -3,7 +3,7 @@ package com.huanshankeji.compose.web.dom.ext import org.w3c.dom.HTMLElement /** - * @see com.huanshankeji.compose.web.attributes.onInput + * @see com.huanshankeji.compose.web.attributes.ext.onInput */ val HTMLElement.value: String get() = asDynamic().value as String From 71810a501412e491e6b2eb70296a009b8f6b777a Mon Sep 17 00:00:00 2001 From: Shreck Ye Date: Thu, 2 May 2024 17:31:21 +0800 Subject: [PATCH 23/34] Add the `MdIcon` composable --- .../compose/html/material3/MdIcon.kt | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MdIcon.kt diff --git a/compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MdIcon.kt b/compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MdIcon.kt new file mode 100644 index 0000000..afe2bb6 --- /dev/null +++ b/compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MdIcon.kt @@ -0,0 +1,32 @@ +package com.huanshankeji.compose.html.material3 + +import androidx.compose.runtime.Composable +import androidx.compose.runtime.DisposableEffect +import com.huanshankeji.compose.web.attributes.Attrs +import com.huanshankeji.compose.web.attributes.attr +import org.jetbrains.compose.web.dom.TagElement +import org.jetbrains.compose.web.dom.Text +import org.w3c.dom.HTMLElement + +// https://github.com/material-components/material-web/blob/main/docs/components/icon.md + +/** + * @param content see https://github.com/material-components/material-web/blob/main/docs/components/icon.md#usage + */ +@Composable +fun MdIcon(filled: Boolean? = null, attrs: Attrs?, content: @Composable () -> Unit) { + require("@material/web/icon/icon.js") + + @Suppress("RemoveExplicitTypeArguments") + TagElement("md-icon", { + filled?.let { attr("filled", it) } + + attrs?.invoke(this) + }) { + content() + } +} + +@Composable +fun MdIcon(filled: Boolean? = null, attrs: Attrs?, materialIconName: String) = + MdIcon(filled, attrs) { Text(materialIconName) } From b36f57e3b99db7135f9f9463b81b4457c0f11a11 Mon Sep 17 00:00:00 2001 From: Shreck Ye Date: Fri, 3 May 2024 00:29:16 +0800 Subject: [PATCH 24/34] Add a section in the README.md about Material Symbols & Icons --- README.md | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/README.md b/README.md index 0b5b958..4c5f869 100644 --- a/README.md +++ b/README.md @@ -52,3 +52,41 @@ plugins { ``` 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 + + ``` + +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). From 6b8f505c78f9f8d7745d8744fec0b491f1ef6e70 Mon Sep 17 00:00:00 2001 From: Shreck Ye Date: Sun, 5 May 2024 01:32:48 +0800 Subject: [PATCH 25/34] Add the icon button composables --- .../compose/web/attributes/ext/Attrs.kt | 4 + .../compose/html/material3/MdButton.kt | 3 +- .../compose/html/material3/MdIconButton.kt | 189 ++++++++++++++++++ 3 files changed, 195 insertions(+), 1 deletion(-) create mode 100644 compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MdIconButton.kt diff --git a/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/ext/Attrs.kt b/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/ext/Attrs.kt index c023d38..4cf3485 100644 --- a/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/ext/Attrs.kt +++ b/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/ext/Attrs.kt @@ -137,3 +137,7 @@ fun AttrsScope<*>.autoCapitalizeRequiringValid(value: String) { fun AttrsScope<*>.enterKeyHintIfValid(value: String) { if (value in EnterKeyHint.valueSet) enterKeyHint(value) } + + +fun AttrsScope<*>.selected(value: Boolean?) = + attrIfNotNull("selected", value) diff --git a/compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MdButton.kt b/compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MdButton.kt index 19901b1..52dde19 100644 --- a/compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MdButton.kt +++ b/compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MdButton.kt @@ -3,6 +3,7 @@ package com.huanshankeji.compose.html.material3 import androidx.compose.runtime.Composable import com.huanshankeji.compose.web.attributes.Attrs import com.huanshankeji.compose.web.attributes.ext.* +import com.huanshankeji.compose.web.attributes.slot import org.jetbrains.compose.web.attributes.AttrsScope import org.jetbrains.compose.web.dom.ElementScope import org.jetbrains.compose.web.dom.TagElement @@ -202,5 +203,5 @@ fun MdTextButton( class MdButtonScope(val elementScope: ElementScope) { fun AttrsScope<*>.slotEqIcon() = - attr("slot", "icon") + slot("icon") } diff --git a/compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MdIconButton.kt b/compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MdIconButton.kt new file mode 100644 index 0000000..e702297 --- /dev/null +++ b/compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MdIconButton.kt @@ -0,0 +1,189 @@ +package com.huanshankeji.compose.html.material3 + +import androidx.compose.runtime.Composable +import com.huanshankeji.compose.web.attributes.Attrs +import com.huanshankeji.compose.web.attributes.attr +import com.huanshankeji.compose.web.attributes.ext.* +import com.huanshankeji.compose.web.attributes.slot +import org.jetbrains.compose.web.attributes.AttrsScope +import org.jetbrains.compose.web.dom.ElementScope +import org.jetbrains.compose.web.dom.TagElement +import org.w3c.dom.HTMLElement + + +/* +https://github.com/material-components/material-web/blob/main/docs/components/icon-button.md +https://material-web.dev/components/icon-button/ +https://material-web.dev/components/icon-button/stories/ + */ + + +@Composable +private fun CommonMdIconButton( + tagName: String, + disabled: Boolean?, + flipIconInRtl: Boolean?, + href: String?, + target: String?, + ariaLabelSelected: String?, + toggle: Boolean?, + selected: Boolean?, + type: String?, + value: String?, + attrs: Attrs?, + content: @Composable MdIconButtonScope.() -> Unit +) = + @Suppress("RemoveExplicitTypeArguments") + TagElement( + tagName, + { + disabled(disabled) + flipIconInRtl?.let { attr("flip-icon-in-rtl", it) } + href(href) + target(target) + ariaLabelSelected?.let { attr("aria-label-selected", it) } + toggle?.let { attr("toggle", it) } + selected(selected) + type(type) + value(value) + + attrs?.invoke(this) + } + ) { + MdIconButtonScope(this).content() + } + + +@Composable +fun MdIconButton( + disabled: Boolean? = null, + flipIconInRtl: Boolean? = null, + href: String? = null, + target: String? = null, + ariaLabelSelected: String? = null, + toggle: Boolean? = null, + selected: Boolean? = null, + type: String? = null, + value: String? = null, + attrs: Attrs? = null, + content: @Composable MdIconButtonScope.() -> Unit +) { + require("@material/web/iconbutton/icon-button.js") + + CommonMdIconButton( + "md-icon-button", + disabled, + flipIconInRtl, + href, + target, + ariaLabelSelected, + toggle, + selected, + type, + value, + attrs, + content + ) +} + +@Composable +fun MdFilledIconButton( + disabled: Boolean? = null, + flipIconInRtl: Boolean? = null, + href: String? = null, + target: String? = null, + ariaLabelSelected: String? = null, + toggle: Boolean? = null, + selected: Boolean? = null, + type: String? = null, + value: String? = null, + attrs: Attrs? = null, + content: @Composable MdIconButtonScope.() -> Unit +) { + require("@material/web/iconbutton/filled-icon-button.js") + + CommonMdIconButton( + "md-filled-icon-button", + disabled, + flipIconInRtl, + href, + target, + ariaLabelSelected, + toggle, + selected, + type, + value, + attrs, + content + ) +} + +@Composable +fun MdFilledTonalIconButton( + disabled: Boolean? = null, + flipIconInRtl: Boolean? = null, + href: String? = null, + target: String? = null, + ariaLabelSelected: String? = null, + toggle: Boolean? = null, + selected: Boolean? = null, + type: String? = null, + value: String? = null, + attrs: Attrs? = null, + content: @Composable MdIconButtonScope.() -> Unit +) { + require("@material/web/iconbutton/filled-tonal-icon-button.js") + + CommonMdIconButton( + "md-filled-tonal-icon-button", + disabled, + flipIconInRtl, + href, + target, + ariaLabelSelected, + toggle, + selected, + type, + value, + attrs, + content + ) +} + +@Composable +fun MdOutlinedIconButton( + disabled: Boolean? = null, + flipIconInRtl: Boolean? = null, + href: String? = null, + target: String? = null, + ariaLabelSelected: String? = null, + toggle: Boolean? = null, + selected: Boolean? = null, + type: String? = null, + value: String? = null, + attrs: Attrs? = null, + content: @Composable MdIconButtonScope.() -> Unit +) { + require("@material/web/iconbutton/outlined-icon-button.js") + + CommonMdIconButton( + "md-outlined-icon-button", + disabled, + flipIconInRtl, + href, + target, + ariaLabelSelected, + toggle, + selected, + type, + value, + attrs, + content + ) +} + + +class MdIconButtonScope(val elementScope: ElementScope) { + fun AttrsScope<*>.slotEqSelected() = + slot("selected") +} From 5b47847b0bb7c15657dde7a39ed79005dd9fdd04 Mon Sep 17 00:00:00 2001 From: Shreck Ye Date: Sun, 5 May 2024 10:16:28 +0800 Subject: [PATCH 26/34] Add a setter too for `HTMLElement.value` --- .../kotlin/com/huanshankeji/compose/web/dom/ext/dom.kt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/dom/ext/dom.kt b/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/dom/ext/dom.kt index f676732..b1a0b08 100644 --- a/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/dom/ext/dom.kt +++ b/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/dom/ext/dom.kt @@ -5,5 +5,8 @@ import org.w3c.dom.HTMLElement /** * @see com.huanshankeji.compose.web.attributes.ext.onInput */ -val HTMLElement.value: String +var HTMLElement.value: String get() = asDynamic().value as String + set(value) { + asDynamic().value = value + } From 8f3692e80a5ac32b6173bbeb16f99bca40ab6cda Mon Sep 17 00:00:00 2001 From: Shreck Ye Date: Sun, 5 May 2024 22:18:27 +0800 Subject: [PATCH 27/34] Add the FAB composables --- .../compose/web/attributes/ext/Attrs.kt | 1 + .../compose/html/material3/MdFab.kt | 72 +++++++++++++++++++ 2 files changed, 73 insertions(+) create mode 100644 compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MdFab.kt diff --git a/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/ext/Attrs.kt b/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/ext/Attrs.kt index 4cf3485..2f64bf8 100644 --- a/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/ext/Attrs.kt +++ b/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/ext/Attrs.kt @@ -69,6 +69,7 @@ fun AttrsScope<*>.required(value: Boolean?) = attrIfNotNull("required", value) // https://www.geeksforgeeks.org/html-label-attribute/ +// https://www.w3schools.com/tags/att_label.asp fun AttrsScope<*>.label(value: String?) = attrIfNotNull("label", value) diff --git a/compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MdFab.kt b/compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MdFab.kt new file mode 100644 index 0000000..ff4c93a --- /dev/null +++ b/compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MdFab.kt @@ -0,0 +1,72 @@ +package com.huanshankeji.compose.html.material3 + +import androidx.compose.runtime.Composable +import com.huanshankeji.compose.web.attributes.Attrs +import com.huanshankeji.compose.web.attributes.attr +import com.huanshankeji.compose.web.attributes.ext.label +import com.huanshankeji.compose.web.attributes.slot +import org.jetbrains.compose.web.attributes.AttrsScope +import org.jetbrains.compose.web.dom.ElementScope +import org.jetbrains.compose.web.dom.TagElement +import org.w3c.dom.HTMLElement + +/* +https://github.com/material-components/material-web/blob/main/docs/components/fab.md +https://material-web.dev/components/fab/ +https://material-web.dev/components/fab/stories/ + */ + +@Composable +private fun CommonMdFab( + tagName: String, + variant: String?, + size: String?, + label: String?, + lowered: Boolean?, + attrs: Attrs?, + content: @Composable (MdFabScope.() -> Unit)? +) = + TagElement(tagName, { + variant?.let { attr("variant", it) } + size?.let { attr("size", it) } + label?.let { label(it) } + lowered?.let { attr("lowered", it) } + + attrs?.invoke(this) + }, content?.let { + { MdFabScope(this).it() } + }) + +@Composable +fun MdFab( + variant: String? = null, + size: String? = null, + label: String? = null, + lowered: Boolean? = null, + attrs: Attrs? = null, + content: @Composable (MdFabScope.() -> Unit)? +) { + require("@material/web/fab/fab.js") + + CommonMdFab("md-fab", variant, size, label, lowered, attrs, content) +} + +@Composable +fun MdBrandedFab( + variant: String? = null, + size: String? = null, + label: String? = null, + lowered: Boolean? = null, + attrs: Attrs? = null, + content: @Composable (MdFabScope.() -> Unit)? +) { + require("@material/web/fab/branded-fab.js") + + CommonMdFab("md-branded-fab", variant, size, label, lowered, attrs, content) +} + + +class MdFabScope(val elementScope: ElementScope) { + fun AttrsScope<*>.slotEqIcon() = + slot("icon") +} From 8746b5742c3c70785e4bfcbbbeff4e3a812f2831 Mon Sep 17 00:00:00 2001 From: Shreck Ye Date: Tue, 7 May 2024 11:54:24 +0800 Subject: [PATCH 28/34] Add the `MdList` and `MdListItem` composables --- .../compose/html/material3/MdList.kt | 91 +++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MdList.kt diff --git a/compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MdList.kt b/compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MdList.kt new file mode 100644 index 0000000..0ae50a4 --- /dev/null +++ b/compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MdList.kt @@ -0,0 +1,91 @@ +package com.huanshankeji.compose.html.material3 + +import androidx.compose.runtime.Composable +import com.huanshankeji.compose.web.attributes.Attrs +import com.huanshankeji.compose.web.attributes.ext.disabled +import com.huanshankeji.compose.web.attributes.ext.href +import com.huanshankeji.compose.web.attributes.ext.target +import com.huanshankeji.compose.web.attributes.ext.type +import com.huanshankeji.compose.web.attributes.slot +import org.jetbrains.compose.web.attributes.AttrsScope +import org.jetbrains.compose.web.dom.ElementScope +import org.jetbrains.compose.web.dom.TagElement +import org.w3c.dom.HTMLElement + +/* +https://github.com/material-components/material-web/blob/main/docs/components/list.md +https://material-web.dev/components/list/ +https://material-web.dev/components/list/stories/ + */ + +@Composable +fun MdList(attrs: Attrs? = null, content: @Composable MdListScope.() -> Unit) { + require("@material/web/list/list.js") + + TagElement("md-list", attrs) { + MdListScope(this).content() + } +} + +class MdListScope(val elementScope: ElementScope) { + @Composable + fun MdListItem( + disabled: Boolean? = null, + type: MdListItemType? = null, + href: String? = null, + target: String? = null, + attrs: Attrs? = null, + content: @Composable MdListItemScope.() -> Unit + ) = + @OptIn(ExposedMdListApi::class) + com.huanshankeji.compose.html.material3.MdListItem(disabled, type, href, target, attrs, content) +} + + +@RequiresOptIn( + "An `MdListItem` is usually in an `MdList`. This component is exposed and should be used carefully. In most cases try to use the one in `MdListScope` instead.", + RequiresOptIn.Level.WARNING +) +@Retention(AnnotationRetention.BINARY) +annotation class ExposedMdListApi + +@ExposedMdListApi +@Composable +fun MdListItem( + disabled: Boolean? = null, + type: MdListItemType? = null, + href: String? = null, + target: String? = null, + attrs: Attrs? = null, + content: @Composable MdListItemScope.() -> Unit +) { + require("@material/web/list/list-item.js") + + //@Suppress("RemoveExplicitTypeArguments") + TagElement("md-list-item", { + disabled(disabled) + type(type?.stringValue) + href(href) + target(target) + + attrs?.invoke(this) + }) { + MdListItemScope(this).content() + } +} + +enum class MdListItemType(val stringValue: String) { + Text("text"), Link("link"), Button("button") +} + +class MdListItemScope(val elementScope: ElementScope) { + enum class Slot(val stringValue: String) { + Headline("headline"), + Start("start"), End("end"), + SupportingText("supporting-text"), TrailingSupportingText("trailing-supporting-text"), + Overline("overline") + } + + fun AttrsScope<*>.slot(value: Slot) = + slot(value.stringValue) +} From 49057370fb8d9fd43b181bae4455ee277fc97b75 Mon Sep 17 00:00:00 2001 From: Shreck Ye Date: Thu, 9 May 2024 09:06:26 +0800 Subject: [PATCH 29/34] Add the card composables --- .../html/material3/MaterialWebLabsApi.kt | 9 ++++ .../compose/html/material3/MdCard.kt | 45 +++++++++++++++++++ 2 files changed, 54 insertions(+) create mode 100644 compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MaterialWebLabsApi.kt create mode 100644 compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MdCard.kt diff --git a/compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MaterialWebLabsApi.kt b/compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MaterialWebLabsApi.kt new file mode 100644 index 0000000..c38f120 --- /dev/null +++ b/compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MaterialWebLabsApi.kt @@ -0,0 +1,9 @@ +package com.huanshankeji.compose.html.material3 + +@RequiresOptIn( + "This API depends on components in the Material Web labs directory, which contains experimental features that are not recommended for production. " + + "See https://github.com/material-components/material-web/tree/main/labs for more details.", + RequiresOptIn.Level.WARNING +) +@Retention(AnnotationRetention.BINARY) +annotation class MaterialWebLabsApi \ No newline at end of file diff --git a/compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MdCard.kt b/compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MdCard.kt new file mode 100644 index 0000000..7ac69c5 --- /dev/null +++ b/compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MdCard.kt @@ -0,0 +1,45 @@ +package com.huanshankeji.compose.html.material3 + +import androidx.compose.runtime.Composable +import com.huanshankeji.compose.web.attributes.Attrs +import org.jetbrains.compose.web.dom.ElementScope +import org.jetbrains.compose.web.dom.TagElement +import org.w3c.dom.HTMLElement + +/* +https://github.com/material-components/material-web/blob/main/labs/card/internal/card.ts +https://github.com/material-components/material-web/blob/main/labs/card/demo/stories.ts + */ + +@MaterialWebLabsApi +@Composable +fun MdElevatedCard( + attrs: Attrs? = null, + content: @Composable (ElementScope.() -> Unit)? +) { + require("@material/web/labs/card/elevated-card.js") + + TagElement("md-elevated-card", attrs, content) +} + +@MaterialWebLabsApi +@Composable +fun MdFilledCard( + attrs: Attrs? = null, + content: @Composable (ElementScope.() -> Unit)? +) { + require("@material/web/labs/card/filled-card.js") + + TagElement("md-filled-card", attrs, content) +} + +@MaterialWebLabsApi +@Composable +fun MdOutlinedCard( + attrs: Attrs? = null, + content: @Composable (ElementScope.() -> Unit)? +) { + require("@material/web/labs/card/outlined-card.js") + + TagElement("md-outlined-card", attrs, content) +} From 414a42d87ab31d9fbc8fa6e58e4f01a8f134c85c Mon Sep 17 00:00:00 2001 From: Shreck Ye Date: Thu, 9 May 2024 17:44:47 +0800 Subject: [PATCH 30/34] Add the `MdNavigationBar` and `MdNavigationTab` composables --- .../compose/web/attributes/Attrs.kt | 4 +- .../compose/html/material3/MdNavigationBar.kt | 31 +++++++++++ .../compose/html/material3/MdNavigationTab.kt | 52 +++++++++++++++++++ 3 files changed, 85 insertions(+), 2 deletions(-) create mode 100644 compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MdNavigationBar.kt create mode 100644 compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MdNavigationTab.kt diff --git a/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/Attrs.kt b/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/Attrs.kt index 97360e9..25781c9 100644 --- a/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/Attrs.kt +++ b/compose-html-common/src/jsMain/kotlin/com/huanshankeji/compose/web/attributes/Attrs.kt @@ -26,8 +26,8 @@ fun AttrsScope<*>.attrIfNotNull(attr: String, value: String?) { value?.let { attr(attr, it) } } -fun AttrsScope<*>.attrIfNotNull(attr: String, isPresent: Boolean?) { - isPresent?.let { attr(attr, it) } +fun AttrsScope<*>.attrIfNotNull(attr: String, value: Boolean?) { + value?.let { attr(attr, it) } } fun AttrsScope<*>.attrIfNotNull(attr: String, value: Int?) { diff --git a/compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MdNavigationBar.kt b/compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MdNavigationBar.kt new file mode 100644 index 0000000..81ba624 --- /dev/null +++ b/compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MdNavigationBar.kt @@ -0,0 +1,31 @@ +package com.huanshankeji.compose.html.material3 + +import androidx.compose.runtime.Composable +import com.huanshankeji.compose.web.attributes.Attrs +import com.huanshankeji.compose.web.attributes.attrIfNotNull +import org.jetbrains.compose.web.dom.ElementScope +import org.jetbrains.compose.web.dom.TagElement +import org.w3c.dom.HTMLElement + +/* +https://github.com/material-components/material-web/blob/main/labs/navigationbar/internal/navigation-bar.ts +https://github.com/material-components/material-web/blob/main/labs/navigationbar/demo/stories.ts + */ + +@MaterialWebLabsApi +@Composable +fun MdNavigationBar( + activeIndex: Int? = null, + hideInactiveLabels: Boolean? = null, + attrs: Attrs? = null, + content: @Composable (ElementScope.() -> Unit)? +) { + require("@material/web/labs/navigationbar/navigation-bar.js") + + TagElement("md-navigation-bar", { + attrIfNotNull("active-index", activeIndex) + attrIfNotNull("hide-inactive-labels", hideInactiveLabels) + + attrs?.invoke(this) + }, content) +} diff --git a/compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MdNavigationTab.kt b/compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MdNavigationTab.kt new file mode 100644 index 0000000..9537eb4 --- /dev/null +++ b/compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MdNavigationTab.kt @@ -0,0 +1,52 @@ +package com.huanshankeji.compose.html.material3 + +import androidx.compose.runtime.Composable +import com.huanshankeji.compose.web.attributes.Attrs +import com.huanshankeji.compose.web.attributes.attrIfNotNull +import com.huanshankeji.compose.web.attributes.ext.disabled +import com.huanshankeji.compose.web.attributes.ext.label +import com.huanshankeji.compose.web.attributes.slot +import org.jetbrains.compose.web.attributes.AttrsScope +import org.jetbrains.compose.web.dom.ElementScope +import org.jetbrains.compose.web.dom.TagElement +import org.w3c.dom.HTMLElement + +/* +https://github.com/material-components/material-web/blob/main/labs/navigationtab/internal/navigation-tab.ts +https://github.com/material-components/material-web/blob/main/labs/navigationbar/demo/stories.ts (navigation bar storybook) + */ + +@MaterialWebLabsApi +@Composable +fun MdNavigationTab( + disabled: Boolean? = null, + active: Boolean? = null, + hideInactiveLabel: Boolean? = null, + label: String? = null, + badgeValue: String? = null, + showBadge: Boolean? = null, + attrs: Attrs? = null, + content: @Composable (MdNavigationTabScope.() -> Unit)? +) { + require("@material/web/labs/navigationtab/navigation-tab.js") + + TagElement("md-navigation-tab", { + disabled(disabled) + attrIfNotNull("active", active) + attrIfNotNull("hide-inactive-label", hideInactiveLabel) + label(label) + attrIfNotNull("badge-value", badgeValue) + attrIfNotNull("show-badge", showBadge) + + attrs?.invoke(this) + }, content?.let { { MdNavigationTabScope(this).it() } }) +} + +class MdNavigationTabScope(val elementScope: ElementScope) { + enum class Slot(val stringValue: String) { + ActiveIcon("active-icon"), InactiveIcon("inactive-icon") + } + + fun AttrsScope<*>.slot(value: Slot) = + slot(value.stringValue) +} From 905a95427669bb9be434ca52300865ab106fa243 Mon Sep 17 00:00:00 2001 From: Shreck Ye Date: Thu, 9 May 2024 18:00:34 +0800 Subject: [PATCH 31/34] Reformat README.md with VS Code --- README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 4c5f869..5d8863e 100644 --- a/README.md +++ b/README.md @@ -70,11 +70,13 @@ In short, there are 3 ways to add the Material Symbols & Icons dependency: 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() { @@ -82,7 +84,7 @@ In short, there are 3 ways to add the Material Symbols & Icons dependency: 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) From 25bd25db6b86d6b1ce05de912dfcddbe02786f2f Mon Sep 17 00:00:00 2001 From: Shreck Ye Date: Thu, 9 May 2024 20:57:31 +0800 Subject: [PATCH 32/34] Copy "README.md" to "LEGACY_README.md" --- LEGACY_README.md | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 LEGACY_README.md diff --git a/LEGACY_README.md b/LEGACY_README.md new file mode 100644 index 0000000..b7a3ca9 --- /dev/null +++ b/LEGACY_README.md @@ -0,0 +1,42 @@ +# 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) + +Some Material components for Compose HTML, 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) + +~~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.~~ + +**This project is not currently under active development. Here is a list of reasons and alternatives:** + +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 HTML. +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. + +## Instructions on how to use + +Some configurations are needed to use this library due to the immaturities of this project and Kotlin/JS. + +### Add the dependency + +```kotlin +implementation("com.huanshankeji:compose-web-material:$version") +``` + +### In code + +Call `mwcRequires()` in your `main` function before calling any component Composable functions. + +### Kotlin/JS Webpack configuration + +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. + +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: + +```kotlin +plugins { + id("com.huanshankeji.compose-web-material-conventions") version someVersion +} +``` + +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. From ef04079550229a318301d59210dd67b2f559bb36 Mon Sep 17 00:00:00 2001 From: Shreck Ye Date: Thu, 9 May 2024 23:23:35 +0800 Subject: [PATCH 33/34] Update README.md and extract a legacy README according to the latest Material 3 updates, and slight update the project structure --- LEGACY_README.md | 37 +++++++--- README.md | 67 +++++++++---------- .../html/material3/MaterialWebLabsApi.kt | 2 +- gradle-plugins/build.gradle.kts | 2 +- ...ml-material-conventions-legacy.gradle.kts} | 0 {demo => legacy/demo}/html/demo.html | 0 .../webpack.config.d/further_adjustments.js | 0 settings.gradle.kts | 2 +- 8 files changed, 63 insertions(+), 47 deletions(-) rename gradle-plugins/src/main/kotlin/com/huanshankeji/{compose-html-material-conventions.gradle.kts => compose-html-material-conventions-legacy.gradle.kts} (100%) rename {demo => legacy/demo}/html/demo.html (100%) rename {demo => legacy/demo}/webpack.config.d/further_adjustments.js (100%) diff --git a/LEGACY_README.md b/LEGACY_README.md index b7a3ca9..b10b57d 100644 --- a/LEGACY_README.md +++ b/LEGACY_README.md @@ -1,17 +1,14 @@ -# Compose HTML Material +# Compose HTML Material (legacy Material 2) -[![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-material-legacy)](https://search.maven.org/artifact/com.huanshankeji/compose-html-material-legacy) +[![Gradle Plugin Portal](https://img.shields.io/gradle-plugin-portal/v/com.huanshankeji.compose-html-material-conventions-legacy)](https://plugins.gradle.org/plugin/com.huanshankeji.compose-html-material-conventions-legacy) -Some Material components for Compose HTML, 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) +Some legacy Material 2 components for Compose HTML, based on [the obsolete `mwc` branch of Material Web](https://github.com/material-components/material-web/tree/mwc) (preferred) and [Material Components for the web (or material-components-web, or `mdc`)](https://github.com/material-components/material-components-web) (fallback) -~~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.~~ +**There will be no further development effort in this legacy Material 2 portion of this project. Here is a list of reasons and alternatives:** -**This project is not currently under active development. Here is a list of reasons and alternatives:** - -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. The [material-web](https://github.com/material-components/material-web) team is working on Material 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-html-material-legacy` subproject](/compose-html-material-legacy) 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 HTML. -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. ## Instructions on how to use @@ -19,10 +16,18 @@ Some configurations are needed to use this library due to the immaturities of th ### Add the dependency +Prior to v0.3.0: + ```kotlin implementation("com.huanshankeji:compose-web-material:$version") ``` +Since v0.3.0: + +```kotlin +implementation("com.huanshankeji:compose-html-material-legacy:$version") +``` + ### In code Call `mwcRequires()` in your `main` function before calling any component Composable functions. @@ -31,7 +36,9 @@ Call `mwcRequires()` in your `main` function before calling any component Compos 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. -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: +If you use a version prior to v0.3.0, 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: + +Prior to v0.3.0: ```kotlin plugins { @@ -39,4 +46,14 @@ plugins { } ``` +Since v0.3.0: + +```kotlin +plugins { + id("com.huanshankeji.compose-web-material-conventions-legacy") version someVersion +} +``` + 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. + +Also note that there is [a new approach to adding CSS and SCSS support in the Kotlin Gradle Plugin since 1.8](https://kotlinlang.org/docs/whatsnew18.html#new-approach-to-adding-css-support-to-your-project), which replaces the function of this plugin. diff --git a/README.md b/README.md index 5d8863e..3b15e36 100644 --- a/README.md +++ b/README.md @@ -1,58 +1,57 @@ # Compose HTML Material -[![Maven Central](https://img.shields.io/maven-central/v/com.huanshankeji/compose-html-material3)](https://search.maven.org/artifact/com.huanshankeji/compose-html-material) -[![Gradle Plugin Portal](https://img.shields.io/gradle-plugin-portal/v/com.huanshankeji.compose-html-material-conventions)](https://plugins.gradle.org/plugin/com.huanshankeji.compose-html-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 HTML, with legacy Material 2 wrapper components based on [the obsolete `mwc` branch of Material Web](https://github.com/material-components/material-web/tree/mwc) (preferred) and [Material Components for the web (or material-components-web, or `mdc`)](https://github.com/material-components/material-components-web) (fallback), and Material 3 wrapper components based on [Material Web](https://github.com/material-components/material-web) +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). -**The Material 2 portion of 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 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-html-material-legacy` subproject](compose-html-material-legacy) 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 HTML. -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-html-common` subproject](compose-html-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 - -Prior to v0.3.0: - -```kotlin -implementation("com.huanshankeji:compose-web-common:$version") -implementation("com.huanshankeji:compose-web-material:$version") -``` +- `MdElevatedButton`, `MdFilledButton`, `MdFilledTonalButton`, `MdOutlinedButton`, `MdTextButton` +- `MdCheckbox` +- `MdFab`, `MdBrandedFab` +- `MdIcon` +- `MdIconButton`, `MdFilledIconButton`, `MdFilledTonalIconButton`, `MdOutlinedIconButton` +- `MdList`, `MdListItem` +- `MdSwitch`, `LabelWithMdSwitch` +- `MdFilledTextField`, `MdOutlinedTextField` -Since v0.3.0: +### "labs" components -```kotlin -implementation("com.huanshankeji:compose-html-common:$version") -implementation("com.huanshankeji:compose-html-material3:$version") - -implementation("com.huanshankeji:compose-html-material-legacy:$version") // Legacy Material 2 -``` +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: -### In code +- `MdElevatedCard`, `MdOutlinedCard` +- `MdNavigationBar` +- `MdNavigationTab` -Call `mwcRequires()` in your `main` function before calling any component Composable functions. +You should opt-in to `@MaterialWebLabsApi` to use them. -### Kotlin/JS Webpack configuration +## Brief Instructions -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. +### Add the dependency -If you use a version prior to v0.3.0, 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). diff --git a/compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MaterialWebLabsApi.kt b/compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MaterialWebLabsApi.kt index c38f120..8090682 100644 --- a/compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MaterialWebLabsApi.kt +++ b/compose-html-material3/src/jsMain/kotlin/com/huanshankeji/compose/html/material3/MaterialWebLabsApi.kt @@ -1,7 +1,7 @@ package com.huanshankeji.compose.html.material3 @RequiresOptIn( - "This API depends on components in the Material Web labs directory, which contains experimental features that are not recommended for production. " + + "This API depends on components in the Material Web \"labs\" directory, which contains experimental features that are not recommended for production. " + "See https://github.com/material-components/material-web/tree/main/labs for more details.", RequiresOptIn.Level.WARNING ) diff --git a/gradle-plugins/build.gradle.kts b/gradle-plugins/build.gradle.kts index db060c0..88ce53f 100644 --- a/gradle-plugins/build.gradle.kts +++ b/gradle-plugins/build.gradle.kts @@ -35,7 +35,7 @@ gradlePlugin { vcsUrl.set("${website.get()}.git") plugins { - getByName("com.huanshankeji.compose-html-material-conventions") { + getByName("com.huanshankeji.compose-html-material-conventions-legacy") { displayName = "Compose HTML Material conventions" description = "This plugin adds the needed Maven dependencies and npm devDependencies (mainly for Webpack) for a Compose HTML project with Material components." diff --git a/gradle-plugins/src/main/kotlin/com/huanshankeji/compose-html-material-conventions.gradle.kts b/gradle-plugins/src/main/kotlin/com/huanshankeji/compose-html-material-conventions-legacy.gradle.kts similarity index 100% rename from gradle-plugins/src/main/kotlin/com/huanshankeji/compose-html-material-conventions.gradle.kts rename to gradle-plugins/src/main/kotlin/com/huanshankeji/compose-html-material-conventions-legacy.gradle.kts diff --git a/demo/html/demo.html b/legacy/demo/html/demo.html similarity index 100% rename from demo/html/demo.html rename to legacy/demo/html/demo.html diff --git a/demo/webpack.config.d/further_adjustments.js b/legacy/demo/webpack.config.d/further_adjustments.js similarity index 100% rename from demo/webpack.config.d/further_adjustments.js rename to legacy/demo/webpack.config.d/further_adjustments.js diff --git a/settings.gradle.kts b/settings.gradle.kts index 4ebf6ef..9cedcae 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -4,4 +4,4 @@ include("compose-html-common") include("compose-html-material-legacy") include("compose-html-material3") include("gradle-plugins") -project(":gradle-plugins").name = rootProject.name + "-gradle-plugins" +project(":gradle-plugins").name = "compose-html-material-gradle-plugins-legacy" From 05325adc1b1163946d89da0e8229fdb989b82444 Mon Sep 17 00:00:00 2001 From: Shreck Ye Date: Thu, 9 May 2024 23:25:17 +0800 Subject: [PATCH 34/34] Move the legacy README into the "legacy" directory --- README.md | 2 +- LEGACY_README.md => legacy/README.md | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename LEGACY_README.md => legacy/README.md (100%) diff --git a/README.md b/README.md index 3b15e36..1350dc3 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ Material 3 wrapper components for Compose HTML based on [Material Web](https://g 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). -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). +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). ## Supported components diff --git a/LEGACY_README.md b/legacy/README.md similarity index 100% rename from LEGACY_README.md rename to legacy/README.md