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