Shagen Ogandzhanian
3 years ago
2 changed files with 237 additions and 0 deletions
@ -0,0 +1,107 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2020-2021 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 |
||||||
|
import org.w3c.dom.css.CSS |
||||||
|
|
||||||
|
fun interface FilterFunction { |
||||||
|
fun apply(): String |
||||||
|
} |
||||||
|
|
||||||
|
interface FilterBuilder { |
||||||
|
fun blur(radius: CSSLengthValue) |
||||||
|
|
||||||
|
fun brightness(amount: Number) |
||||||
|
fun brightness(amount: CSSPercentageValue) |
||||||
|
|
||||||
|
fun dropShadow(offsetX: CSSLengthValue, offsetY: CSSLengthValue) |
||||||
|
fun dropShadow(offsetX: CSSLengthValue, offsetY: CSSLengthValue, blurRadius: CSSLengthValue) |
||||||
|
fun dropShadow(offsetX: CSSLengthValue, offsetY: CSSLengthValue, color: CSSColorValue) |
||||||
|
fun dropShadow(offsetX: CSSLengthValue, offsetY: CSSLengthValue, blurRadius: CSSLengthValue, color: CSSColorValue) |
||||||
|
|
||||||
|
fun contrast(amount: Number) |
||||||
|
fun contrast(amount: CSSPercentageValue) |
||||||
|
|
||||||
|
fun grayscale(amount: Number) |
||||||
|
fun grayscale(amount: CSSPercentageValue) |
||||||
|
|
||||||
|
fun hueRotate(angle: CSSAngleValue) |
||||||
|
|
||||||
|
fun invert(amount: Number) |
||||||
|
fun invert(amount: CSSPercentageValue) |
||||||
|
|
||||||
|
fun opacity(amount: Number) |
||||||
|
fun opacity(amount: CSSPercentageValue) |
||||||
|
|
||||||
|
fun saturate(amount: Number) |
||||||
|
fun saturate(amount: CSSPercentageValue) |
||||||
|
|
||||||
|
fun sepia(amount: Number) |
||||||
|
fun sepia(amount: CSSPercentageValue) |
||||||
|
} |
||||||
|
|
||||||
|
private class FilterBuilderImplementation : FilterBuilder { |
||||||
|
private val transformations = mutableListOf<FilterFunction>() |
||||||
|
|
||||||
|
override fun blur(radius: CSSLengthValue) { transformations.add { "blur($radius)" } } |
||||||
|
|
||||||
|
override fun brightness(amount: Number) { transformations.add { "brightness($amount)" } } |
||||||
|
override fun brightness(amount: CSSPercentageValue) { transformations.add { "brightness($amount)" } } |
||||||
|
|
||||||
|
override fun contrast(amount: Number) { transformations.add { "contrast($amount)" } } |
||||||
|
override fun contrast(amount: CSSPercentageValue) { transformations.add { "contrast($amount)" } } |
||||||
|
|
||||||
|
override fun grayscale(amount: Number) { transformations.add { "grayscale($amount)" } } |
||||||
|
override fun grayscale(amount: CSSPercentageValue) { transformations.add { "grayscale($amount)" } } |
||||||
|
|
||||||
|
override fun hueRotate(angle: CSSAngleValue) { transformations.add { "hue-rotate($angle)" } } |
||||||
|
|
||||||
|
override fun toString(): String { |
||||||
|
return transformations.joinToString(" ") { it.apply() } |
||||||
|
} |
||||||
|
|
||||||
|
override fun invert(amount: Number) { transformations.add { "invert($amount)" } } |
||||||
|
override fun invert(amount: CSSPercentageValue) { transformations.add { "invert($amount)" } } |
||||||
|
|
||||||
|
override fun opacity(amount: Number) { transformations.add { "opacity($amount)" } } |
||||||
|
override fun opacity(amount: CSSPercentageValue) { transformations.add { "opacity($amount)" } } |
||||||
|
|
||||||
|
override fun saturate(amount: Number) { transformations.add { "saturate($amount)" } } |
||||||
|
override fun saturate(amount: CSSPercentageValue) { transformations.add { "saturate($amount)" } } |
||||||
|
|
||||||
|
override fun sepia(amount: Number) { transformations.add { "sepia($amount)" } } |
||||||
|
override fun sepia(amount: CSSPercentageValue) { transformations.add { "sepia($amount)" } } |
||||||
|
|
||||||
|
override fun dropShadow(offsetX: CSSLengthValue, offsetY: CSSLengthValue) { |
||||||
|
transformations.add { "drop-shadow($offsetX $offsetY)" } |
||||||
|
} |
||||||
|
|
||||||
|
override fun dropShadow(offsetX: CSSLengthValue, offsetY: CSSLengthValue, blurRadius: CSSLengthValue) { |
||||||
|
transformations.add { "drop-shadow($offsetX $offsetY $blurRadius)" } |
||||||
|
} |
||||||
|
|
||||||
|
override fun dropShadow(offsetX: CSSLengthValue, offsetY: CSSLengthValue, color: CSSColorValue) { |
||||||
|
transformations.add { "drop-shadow($offsetX $offsetY $color)" } |
||||||
|
} |
||||||
|
|
||||||
|
override fun dropShadow( |
||||||
|
offsetX: CSSLengthValue, |
||||||
|
offsetY: CSSLengthValue, |
||||||
|
blurRadius: CSSLengthValue, |
||||||
|
color: CSSColorValue |
||||||
|
) { |
||||||
|
transformations.add { "drop-shadow($offsetX $offsetY $blurRadius $color)" } |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@ExperimentalComposeWebApi |
||||||
|
fun StyleBuilder.filter(filterContext: FilterBuilder.() -> Unit) { |
||||||
|
val builder = FilterBuilderImplementation() |
||||||
|
property("filter", builder.apply(filterContext).toString()) |
||||||
|
} |
||||||
|
|
||||||
|
|
@ -0,0 +1,130 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2020-2021 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.core.tests.runTest |
||||||
|
import org.jetbrains.compose.web.css.* |
||||||
|
import org.jetbrains.compose.web.dom.Div |
||||||
|
import org.jetbrains.compose.web.dom.Img |
||||||
|
import kotlin.test.Test |
||||||
|
import kotlin.test.assertEquals |
||||||
|
|
||||||
|
@ExperimentalComposeWebApi |
||||||
|
class FilterTests { |
||||||
|
@Test |
||||||
|
fun blur() = runTest { |
||||||
|
composition { |
||||||
|
Img(src = "icon.png", attrs = { style { filter { blur(10.px) } } }) |
||||||
|
} |
||||||
|
|
||||||
|
assertEquals("blur(10px)", nextChild().style.filter) |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
fun brightness() = runTest { |
||||||
|
composition { |
||||||
|
Div({ style { filter { brightness(1.75) } } }) |
||||||
|
Div({ style { filter { brightness(200.percent) } } }) |
||||||
|
} |
||||||
|
|
||||||
|
assertEquals("brightness(1.75)", nextChild().style.filter) |
||||||
|
assertEquals("brightness(200%)", nextChild().style.filter) |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
fun contrast() = runTest { |
||||||
|
composition { |
||||||
|
Div({ style { filter { contrast(2.75) } } }) |
||||||
|
Div({ style { filter { contrast(177.percent) } } }) |
||||||
|
} |
||||||
|
|
||||||
|
assertEquals("contrast(2.75)", nextChild().style.filter) |
||||||
|
assertEquals("contrast(177%)", nextChild().style.filter) |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
fun grayscale() = runTest { |
||||||
|
composition { |
||||||
|
Div({ style { filter { grayscale(0.15) } } }) |
||||||
|
Div({ style { filter { grayscale(90.percent) } } }) |
||||||
|
} |
||||||
|
|
||||||
|
assertEquals("grayscale(0.15)", nextChild().style.filter) |
||||||
|
assertEquals("grayscale(90%)", nextChild().style.filter) |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
fun hueRotate() = runTest { |
||||||
|
composition { |
||||||
|
Div({ style { filter { hueRotate(90.deg) } } }) |
||||||
|
Div({ style { filter { hueRotate(0.5.turn) } } }) |
||||||
|
} |
||||||
|
|
||||||
|
assertEquals("hue-rotate(90deg)", nextChild().style.filter) |
||||||
|
assertEquals("hue-rotate(0.5turn)", nextChild().style.filter) |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
fun invert() = runTest { |
||||||
|
composition { |
||||||
|
Div({ style { filter { invert(0.75) } } }) |
||||||
|
Div({ style { filter { invert(30.percent) } } }) |
||||||
|
} |
||||||
|
|
||||||
|
assertEquals("invert(0.75)", nextChild().style.filter) |
||||||
|
assertEquals("invert(30%)", nextChild().style.filter) |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
fun opacity() = runTest { |
||||||
|
composition { |
||||||
|
Div({ style { filter { opacity(.25) } } }) |
||||||
|
Div({ style { filter { opacity(30.percent) } } }) |
||||||
|
} |
||||||
|
|
||||||
|
assertEquals("opacity(0.25)", nextChild().style.filter) |
||||||
|
assertEquals("opacity(30%)", nextChild().style.filter) |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
fun saturate() = runTest { |
||||||
|
composition { |
||||||
|
Div({ style { filter { saturate(.25) } } }) |
||||||
|
Div({ style { filter { saturate(20.percent) } } }) |
||||||
|
} |
||||||
|
|
||||||
|
assertEquals("saturate(0.25)", nextChild().style.filter) |
||||||
|
assertEquals("saturate(20%)", nextChild().style.filter) |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
fun sepia() = runTest { |
||||||
|
composition { |
||||||
|
Div({ style { filter { sepia(.95) } } }) |
||||||
|
Div({ style { filter { sepia(80.percent) } } }) |
||||||
|
} |
||||||
|
|
||||||
|
assertEquals("sepia(0.95)", nextChild().style.filter) |
||||||
|
assertEquals("sepia(80%)", nextChild().style.filter) |
||||||
|
} |
||||||
|
|
||||||
|
@Test |
||||||
|
fun dropShadow() = runTest { |
||||||
|
composition { |
||||||
|
Div({ style { filter { dropShadow(10.em, 5.px) } } }) |
||||||
|
Div({ style { filter { dropShadow(7.px, 2.px, 20.px) } } }) |
||||||
|
Div({ style { filter { dropShadow(7.px, 2.px, Color.yellow) } } }) |
||||||
|
Div({ style { filter { dropShadow(16.px, 16.px, 10.px, Color.black) } } }) |
||||||
|
} |
||||||
|
|
||||||
|
assertEquals("drop-shadow(10em 5px)", nextChild().style.filter) |
||||||
|
assertEquals("drop-shadow(7px 2px 20px)", nextChild().style.filter) |
||||||
|
assertEquals("drop-shadow(yellow 7px 2px)", nextChild().style.filter) |
||||||
|
assertEquals("drop-shadow(black 16px 16px 10px)", nextChild().style.filter) |
||||||
|
} |
||||||
|
|
||||||
|
} |
Loading…
Reference in new issue