You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
Igor Demin 113e0f48e0 Fix gradlew persmission 1 year ago
..
.run Compose Multiplatform 1.4.0 docs (#3044) 1 year ago
gradle/wrapper Compose Multiplatform 1.4.0 docs (#3044) 1 year ago
screenshots Compose Multiplatform 1.4.0 docs (#3044) 1 year ago
src/jsMain Compose Multiplatform 1.4.0 docs (#3044) 1 year ago
webpack.config.d Compose Multiplatform 1.4.0 docs (#3044) 1 year ago
.gitignore Compose Multiplatform 1.4.0 docs (#3044) 1 year ago
README.MD Compose Multiplatform 1.4.0 docs (#3044) 1 year ago
build.gradle.kts Compose Multiplatform 1.4.0 docs (#3044) 1 year ago
gradle.properties Compose Multiplatform 1.4.0 docs (#3044) 1 year ago
gradlew Fix gradlew persmission 1 year ago
gradlew.bat Compose Multiplatform 1.4.0 docs (#3044) 1 year ago
settings.gradle.kts Compose Multiplatform 1.4.0 docs (#3044) 1 year ago

README.MD

Run in browser:

./gradlew jsRun

How to use HTML based @Composable functions in JS?

Useful links:

  1. @Composable functions can't be invoked from JS directly (because every @Composable function has implicit parameters added by compiler plugin)
  2. We can wrap @Composable functions into some usual function (with @JsExport) which can be invoked in JS as is.
  3. Every call to a "wrapping" function will create a composition (part of DOM controlled by Compose runtime)
  4. It's important to dispose a composition when it's not needed.
  5. The composition's state can be controlled by creating an arbitrary Controller class, which implements and exposes necessary functions for state updates.

Simplified example (see full example in src/jsMain):

// Composables.kt

@JsExport
abstract class ComposeCounterAppController {
    abstract fun setCount(newCount: Int)
    abstract fun dispose()
}

@JsExport
fun ComposeCounterApp(rootId: String, onCountChange: (Int) -> Unit = {}): ComposeCounterAppController {
    var count: Int by mutableStateOf(0)

    val composition = renderComposable(rootElementId = rootId) {
        // Counter is a @Composable function
        // see full example in src/jsMain
        Counter(count) {
            count = it
            onCountChange(count)
        }
    }

    return object : ComposeCounterAppController() {
        override fun setCount(newCount: Int) {
            count = newCount
        }

        override fun dispose() {
            composition.dispose()
        }
    }
}

Then in JS we can use ComposeCounterApp function:

// see src/jsMain/resources/use_compose.js file for a full example

counterController = MyComposables.ComposeCounterApp('counterByCompose', (newCount) => {
    console.log(`Counter was updated. New value = ${newCount}`);
});

The module name was overridden to make it convenient for usage in JS:

// webpack.config.d/configModuleName.js

config.output = config.output || {};
config.output.library = "MyComposables";

Running Web browser application

  • To run, launch command: ./gradlew :jsBrowserDevelopmentRun
  • Or choose browser configuration in IDE and run it.
    browser-run-configuration.png

Building and using the output

./gradlew jsBrowserProductionWebpack

This will produce the output in build/distributions. Then we can use exported functions from compose-in-js.js (the filename is defined by the project/module name).

<script src="compose-in-js.js"></script>
<script src="use_compose.js"></script>