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