Browse Source
* 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
2 changed files with 185 additions and 0 deletions
@ -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()) |
||||||
|
} |
@ -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…
Reference in new issue