Browse Source

Add support for transition in CSS api. (#2228)

* web: Support for transition in CSS api.

* Use proper name for Transitions class, fix formatting.

* web: add ExperimentalComposeWebApi on transitions CSS API.

* web: Add documentation for transitions CSS API.

* fix: Apply all suggested changes.

* web: Add unit tests to transitions CSS API.

* fix: Update documentation with new methods names.
pull/2307/head
Ayfri 2 years ago committed by GitHub
parent
commit
d85bd8c941
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 105
      web/core/src/jsMain/kotlin/org/jetbrains/compose/web/css/properties/transitions.kt
  2. 80
      web/core/src/jsTest/kotlin/css/TransitionsTests.kt

105
web/core/src/jsMain/kotlin/org/jetbrains/compose/web/css/properties/transitions.kt

@ -0,0 +1,105 @@
/*
* Copyright 2020-2022 JetBrains s.r.o. and respective authors and developers.
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE.txt file.
*/
package org.jetbrains.compose.web.css
import org.jetbrains.compose.web.ExperimentalComposeWebApi
@ExperimentalComposeWebApi
data class Transition(
var property: String? = null,
var duration: CSSSizeValue<out CSSUnitTime>? = null,
var timingFunction: AnimationTimingFunction? = null,
var delay: CSSSizeValue<out CSSUnitTime>? = null,
) {
override fun toString(): String {
if (property == null) return ""
var result = property!!
duration?.let { result += " $it" }
timingFunction?.let { result += " $it" }
delay?.let { result += " $it" }
return result
}
}
@ExperimentalComposeWebApi
fun Transition.duration(value: CSSSizeValue<out CSSUnitTime>): Unit = run { duration = value }
@ExperimentalComposeWebApi
fun Transition.timingFunction(value: AnimationTimingFunction): Unit = run { timingFunction = value }
@ExperimentalComposeWebApi
fun Transition.delay(value: CSSSizeValue<out CSSUnitTime>): Unit = run { delay = value }
@ExperimentalComposeWebApi
data class Transitions(
var transitions: List<Transition> = emptyList(),
private var defaultDuration: CSSSizeValue<out CSSUnitTime>? = null,
private var defaultTimingFunction: AnimationTimingFunction? = null,
private var defaultDelay: CSSSizeValue<out CSSUnitTime>? = null,
) {
override fun toString() =
transitions.distinctBy {
it.property
}.joinToString(", ") {
it.apply {
if (defaultDelay != null && delay == null) delay = defaultDelay!!
if (defaultDuration != null && duration == null) duration = defaultDuration!!
if (defaultTimingFunction != null && timingFunction == null) timingFunction = defaultTimingFunction!!
}.toString()
}
inline operator fun String.invoke(block: Transition.() -> Unit): Unit = Transition().apply(block).let {
it.property = this
transitions += it
}
inline operator fun Iterable<String>.invoke(block: Transition.() -> Unit): Unit = Transition().apply(block).let { transition ->
forEach {
transitions += transition.copy(property = it)
}
}
inline operator fun Array<out String>.invoke(block: Transition.() -> Unit): Unit = Transition().apply(block).let { transition ->
forEach {
transitions += transition.copy(property = it)
}
}
inline fun properties(vararg properties: String, block: Transition.() -> Unit = {}): Unit = properties.invoke(block)
inline fun all(block: Transition.() -> Unit): Unit = Transition().apply(block).let { transition ->
transition.property = "all"
transitions += transition
}
fun defaultDuration(value: CSSSizeValue<out CSSUnitTime>): Unit = run { defaultDuration = value }
fun defaultTimingFunction(value: AnimationTimingFunction): Unit = run { defaultTimingFunction = value }
fun defaultDelay(value: CSSSizeValue<out CSSUnitTime>): Unit = run { defaultDelay = value }
}
@ExperimentalComposeWebApi
/**
* Examples:
* ```
* transitions {
* "width" { duration(1.s) }
* }
*
* transitions {
* defaultDuration(.5.s)
* defaultTimingFunction(AnimationTimingFunction.EaseInOut)
* defaultProperties("width", "height")
* }
* ```
*
* @see https://developer.mozilla.org/en-US/docs/Web/CSS/transition
*/
inline fun StyleScope.transitions(transitions: Transitions.() -> Unit) {
val transitionsValue = Transitions().apply(transitions)
property("transition", transitionsValue.toString())
}

80
web/core/src/jsTest/kotlin/css/TransitionsTests.kt

@ -0,0 +1,80 @@
/*
* Copyright 2020-2022 JetBrains s.r.o. and respective authors and developers.
* Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE.txt file.
*/
package org.jetbrains.compose.web.core.tests.css
import org.jetbrains.compose.web.ExperimentalComposeWebApi
import org.jetbrains.compose.web.css.AnimationTimingFunction
import org.jetbrains.compose.web.css.delay
import org.jetbrains.compose.web.css.duration
import org.jetbrains.compose.web.css.s
import org.jetbrains.compose.web.css.timingFunction
import org.jetbrains.compose.web.css.transitions
import org.jetbrains.compose.web.dom.Div
import org.jetbrains.compose.web.testutils.runTest
import kotlin.test.Test
import kotlin.test.assertEquals
@ExperimentalComposeWebApi
class TransitionsTests {
@Test
fun duration() = runTest {
composition {
Div({ style { transitions { "width" { duration(1.s) } }}})
}
assertEquals("width 1s ease 0s", nextChild().style.transition)
}
@Test
fun multipleProperties() = runTest {
composition {
Div({ style { transitions { "width" { duration(1.s) }; "height" { duration(2.s) } }}})
}
assertEquals("width 1s ease 0s, height 2s ease 0s", nextChild().style.transition)
}
@Test
fun allProperties() = runTest {
composition {
Div({ style { transitions { all { duration(1.s) } }}})
}
assertEquals("all 1s ease 0s", nextChild().style.transition)
}
@Test
fun timingFunction() = runTest {
composition {
Div({ style { transitions { "width" { duration(1.s); timingFunction(AnimationTimingFunction.EaseInOut) }}}})
}
assertEquals("width 1s ease-in-out 0s", nextChild().style.transition)
}
@Test
fun delay() = runTest {
composition {
Div({ style { transitions { "width" { duration(1.s); delay(2.s) }}}})
}
assertEquals("width 1s ease 2s", nextChild().style.transition)
}
@Test
fun properties() = runTest {
composition {
Div({ style { transitions { defaultDuration(1.s); properties("width", "height") }}})
Div({ style { transitions { defaultDuration(1.s); properties("width, height"); "width" { duration(2.s) }}}})
val myList = listOf("width", "height")
Div({ style { transitions { defaultDuration(1.s); myList { duration(2.s) }}}})
}
assertEquals("width 1s ease 0s, height 1s ease 0s", nextChild().style.transition)
assertEquals("width 0s ease 0s, height 1s ease 0s, width 2s ease 0s", nextChild().style.transition)
assertEquals("width 2s ease 0s, height 2s ease 0s", nextChild().style.transition)
}
}
Loading…
Cancel
Save