diff --git a/colorpicker/api/colorpicker.klib.api b/colorpicker/api/colorpicker.klib.api index 50412299..836e9274 100644 --- a/colorpicker/api/colorpicker.klib.api +++ b/colorpicker/api/colorpicker.klib.api @@ -1,5 +1,5 @@ // Klib ABI Dump -// Targets: [iosArm64, iosSimulatorArm64] +// Targets: [iosArm64, iosSimulatorArm64, wasmJs] // Rendering settings: // - Signature version: 2 // - Show manifest properties: true diff --git a/colorpicker/build.gradle.kts b/colorpicker/build.gradle.kts index 240e3e97..10c9adda 100644 --- a/colorpicker/build.gradle.kts +++ b/colorpicker/build.gradle.kts @@ -1,6 +1,7 @@ import com.vanniktech.maven.publish.JavadocJar import com.vanniktech.maven.publish.KotlinMultiplatform import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi +import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl import org.jetbrains.kotlin.gradle.dsl.JvmTarget plugins { @@ -18,6 +19,18 @@ version = providers.gradleProperty("VERSION_NAME").get() kotlin { explicitApi() + // Compose Multiplatform for web. The DSL is still marked experimental in the Kotlin + // Gradle plugin, so the opt-in is required and the shape may change between Kotlin + // versions; the library itself needs no wasm-specific source. + @OptIn(ExperimentalWasmDsl::class) + wasmJs { + browser() + // Required even for a library: without an executable binary webpack does not + // bundle the Skiko runtime, and the browser test target cannot load Compose. + // See https://youtrack.jetbrains.com/issue/CMP-4906 + binaries.executable() + } + jvm() android { diff --git a/colorpicker/src/commonTest/kotlin/codes/side/colorpicker/ui/HueFractionMappingTest.kt b/colorpicker/src/commonTest/kotlin/codes/side/colorpicker/ui/HueFractionMappingTest.kt index 5d719fb7..a7f655da 100644 --- a/colorpicker/src/commonTest/kotlin/codes/side/colorpicker/ui/HueFractionMappingTest.kt +++ b/colorpicker/src/commonTest/kotlin/codes/side/colorpicker/ui/HueFractionMappingTest.kt @@ -1,7 +1,6 @@ package codes.side.colorpicker.ui import codes.side.colorpicker.state.ColorPickerState -import kotlin.math.nextDown import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertTrue @@ -11,6 +10,11 @@ import kotlin.test.assertTrue * the equivalent 0, so the slider must never write exactly 360 — otherwise dragging * the thumb to the right end of the track would snap it back to the far left. */ +// kotlin.math.nextDown is unavailable on wasmJs, and this test runs in commonTest, so it +// compiles for every target. Computed here from the bit pattern rather than reusing the +// implementation's own constant, which would make these assertions circular. +private val JUST_BELOW_360 = Float.fromBits(360f.toRawBits() - 1) + class HueFractionMappingTest { @Test @@ -27,7 +31,7 @@ class HueFractionMappingTest { fun fullFractionMapsJustBelow360() { val hue = hueFromFraction(1f) assertTrue(hue < 360f, "hue at the track end must stay below 360, was $hue") - assertEquals(360f.nextDown(), hue) + assertEquals(JUST_BELOW_360, hue) } @Test @@ -36,7 +40,7 @@ class HueFractionMappingTest { // hue must read back unchanged instead of wrapping to 0. val state = ColorPickerState() state.updateHue(hueFromFraction(1f)) - assertEquals(360f.nextDown(), state.hslColor.hue) + assertEquals(JUST_BELOW_360, state.hslColor.hue) } @Test @@ -58,6 +62,6 @@ class HueFractionMappingTest { state.updateHue(hueFromFraction(1f)) val redisplayedFraction = state.hslColor.hue / 360f state.updateHue(hueFromFraction(redisplayedFraction)) - assertEquals(360f.nextDown(), state.hslColor.hue) + assertEquals(JUST_BELOW_360, state.hslColor.hue) } } diff --git a/kotlin-js-store/wasm/yarn.lock b/kotlin-js-store/wasm/yarn.lock new file mode 100644 index 00000000..62b6bd5f --- /dev/null +++ b/kotlin-js-store/wasm/yarn.lock @@ -0,0 +1,8 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@js-joda/core@3.2.0": + version "3.2.0" + resolved "https://registry.yarnpkg.com/@js-joda/core/-/core-3.2.0.tgz#3e61e21b7b2b8a6be746df1335cf91d70db2a273" + integrity sha512-PMqgJ0sw5B7FKb2d5bWYIoxjri+QlW/Pys7+Rw82jSH0QN3rB05jZ/VrrsUdh1w4+i2kw9JOejXGq/KhDOX7Kg==