Igor Yakovlev
2 years ago
132 changed files with 4767 additions and 875 deletions
@ -0,0 +1,2 @@
|
||||
AGFzbQEAAAABBQFgAAF/AhIBA2VudgZtZW1vcnkCAYACgAIDAgEABwsBB19yZW5kZXIAAApJAUcBA38DQCAAQaAGbCECQQAhAQNAIAEgAmpBAnRBgAhqQf+BgHg2AgAgAUEBaiIBQaAGRw0ACyAAQQFqIgBBkANHDQALQYAICw== |
||||
AGFzbQEAAAABBQFgAAF/AhIBA2VudgZtZW1vcnkCAYACgAIDAgEABwsBB19yZW5kZXIAAApJAUcBA38DQCAAQaAGbCECQQAhAQNAIAEgAmpBAnRBgAhqQf+BgHg2AgAgAUEBaiIBQaAGRw0ACyAAQQFqIgBBkANHDQALQYAICw== -d |
@ -1 +1 @@
|
||||
Subproject commit adf295be1d7ab30f6ab1d291c7f05475b6c50937 |
||||
Subproject commit 8c92cdc4f55931657ce157212723e426a0248d24 |
Binary file not shown.
@ -0,0 +1,5 @@
|
||||
distributionBase=GRADLE_USER_HOME |
||||
distributionPath=wrapper/dists |
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-bin.zip |
||||
zipStoreBase=GRADLE_USER_HOME |
||||
zipStorePath=wrapper/dists |
@ -1,7 +1,6 @@
|
||||
#!/bin/bash |
||||
|
||||
cd "$(dirname "$0")" |
||||
|
||||
pushd .. |
||||
./gradlew $COMPOSE_DEFAULT_GRADLE_ARGS "$@" || exit 1 |
||||
popd |
@ -1,3 +1,4 @@
|
||||
kotlin.code.style=official |
||||
kotlin.version=1.7.10 |
||||
kotlin.version=1.8.255-SNAPSHOT |
||||
compose.version=1.2.0 |
||||
compose.plugin.path=/Users/Igor.Yakovlev/.m2/repository/org/jetbrains/compose/compiler/compiler/0.1.0-SNAPSHOT/compiler-0.1.0-SNAPSHOT.jar |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,159 @@
|
||||
package core |
||||
|
||||
import androidx.compose.runtime.MutableState |
||||
import androidx.compose.runtime.State |
||||
import androidx.compose.runtime.mutableStateOf |
||||
import data.GameFrame |
||||
import data.Tube |
||||
|
||||
@JsFun("() => new Date().getTime()") |
||||
external fun getTime(): Double |
||||
|
||||
/** |
||||
* Game logic |
||||
*/ |
||||
class ComposeBirdGame : Game { |
||||
|
||||
companion object { |
||||
const val COLUMNS = 15 |
||||
const val ROWS = 9 |
||||
const val BIRD_COLUMN = 1 |
||||
private const val TUBES_START_FROM = (COLUMNS * 0.75).toInt() |
||||
const val TOTAL_TUBES = 10 |
||||
private const val TUBE_HORIZONTAL_DISTANCE = 3 |
||||
private const val TUBE_VERTICAL_DISTANCE = 3 |
||||
private const val TUBE_WEIGHT = 500 |
||||
private const val BIRD_WEIGHT = 300 |
||||
} |
||||
|
||||
private val tubeGapRange = TUBE_VERTICAL_DISTANCE until ROWS |
||||
private var tubeLastSteppedAt = 0.0 |
||||
private var birdLastSteppedAt = 0.0 |
||||
private var shouldMoveBirdUp = false |
||||
|
||||
private val _gameFrame: MutableState<GameFrame> by lazy { |
||||
mutableStateOf( |
||||
// First frame |
||||
GameFrame( |
||||
birdPos = ROWS / 2, |
||||
tubes = buildLevel(), |
||||
isGameOver = false, |
||||
isGameWon = false, |
||||
score = 0 |
||||
) |
||||
) |
||||
} |
||||
|
||||
/** |
||||
* To build a random level |
||||
*/ |
||||
private fun buildLevel(): List<Tube> { |
||||
return mutableListOf<Tube>().apply { |
||||
var tubesAdded = 0 |
||||
var tubePosition = 0 |
||||
while (tubesAdded < TOTAL_TUBES) { |
||||
if (tubePosition > TUBES_START_FROM && tubePosition % TUBE_HORIZONTAL_DISTANCE == 0) { // To give space to each tube |
||||
add( |
||||
Tube( |
||||
tubePosition, |
||||
buildRandomTube() |
||||
) |
||||
) |
||||
tubesAdded++ |
||||
} |
||||
tubePosition++ |
||||
} |
||||
} |
||||
} |
||||
|
||||
|
||||
/** |
||||
* To build a random vertical tube/pipe |
||||
*/ |
||||
private fun buildRandomTube(): List<Boolean> { |
||||
// creating a full tube |
||||
val tube = mutableListOf<Boolean>().apply { |
||||
repeat(ROWS) { |
||||
add(true) |
||||
} |
||||
} |
||||
|
||||
// Adding gaps in random middle positions to make it two tubes. |
||||
val gap1 = tubeGapRange.random() |
||||
repeat(TUBE_VERTICAL_DISTANCE) { index -> |
||||
tube[gap1 - index] = false |
||||
} |
||||
|
||||
return tube |
||||
} |
||||
|
||||
override val gameFrame: State<GameFrame> = _gameFrame |
||||
|
||||
override fun step() { |
||||
update { |
||||
val now = getTime() |
||||
|
||||
// Stepping tube |
||||
val tubeDiff = now - tubeLastSteppedAt |
||||
val newTubes = if (tubeDiff > TUBE_WEIGHT) { |
||||
tubeLastSteppedAt = now |
||||
tubes.map { |
||||
it.copy(position = it.position - 1) |
||||
} |
||||
} else { |
||||
tubes |
||||
} |
||||
|
||||
// Stepping bird position |
||||
val birdDiff = now - birdLastSteppedAt |
||||
val newBirdPos = when { |
||||
shouldMoveBirdUp -> { |
||||
birdLastSteppedAt = now |
||||
shouldMoveBirdUp = false |
||||
birdPos - 1 // move up |
||||
} |
||||
birdDiff > BIRD_WEIGHT -> { |
||||
birdLastSteppedAt = now |
||||
birdPos + 1 // move down |
||||
} |
||||
else -> { |
||||
birdPos |
||||
} |
||||
} |
||||
|
||||
val newScore = newTubes.filter { it.position < BIRD_COLUMN }.size // All passed tube |
||||
val newIsGameWon = newScore >= TOTAL_TUBES // If all tubes passed |
||||
|
||||
// Checking if bird gone out |
||||
val newIsGameOver = if (newBirdPos < 0 || newBirdPos >= ROWS || isCollidedWithTube(newBirdPos, tubes)) { |
||||
true |
||||
} else { |
||||
isGameOver |
||||
} |
||||
|
||||
copy( |
||||
isGameOver = newIsGameOver, |
||||
tubes = newTubes, |
||||
birdPos = newBirdPos, |
||||
score = newScore, |
||||
isGameWon = newIsGameWon |
||||
) |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* To check if the bird collided with the tube (collision-detection) |
||||
*/ |
||||
private fun isCollidedWithTube(newBirdPos: Int, tubes: List<Tube>): Boolean { |
||||
val birdTube = tubes.find { it.position == BIRD_COLUMN } |
||||
return birdTube?.coordinates?.get(newBirdPos) ?: false |
||||
} |
||||
|
||||
override fun moveBirdUp() { |
||||
shouldMoveBirdUp = true |
||||
} |
||||
|
||||
private inline fun update(func: GameFrame.() -> GameFrame) { |
||||
_gameFrame.value = _gameFrame.value.func() |
||||
} |
||||
} |
@ -0,0 +1,13 @@
|
||||
package core |
||||
|
||||
import androidx.compose.runtime.State |
||||
import data.GameFrame |
||||
|
||||
/** |
||||
* A generic game interface |
||||
*/ |
||||
interface Game { |
||||
val gameFrame: State<GameFrame> |
||||
fun step() |
||||
fun moveBirdUp() |
||||
} |
@ -0,0 +1,9 @@
|
||||
package data |
||||
|
||||
data class GameFrame( |
||||
val birdPos: Int, |
||||
val tubes: List<Tube>, |
||||
val isGameOver: Boolean, |
||||
val isGameWon : Boolean, |
||||
val score: Int, |
||||
) |
@ -0,0 +1,6 @@
|
||||
package data |
||||
|
||||
data class Tube( |
||||
var position: Int, |
||||
val coordinates: List<Boolean> |
||||
) |
@ -0,0 +1,136 @@
|
||||
import androidx.compose.runtime.Composable |
||||
import androidx.compose.runtime.LaunchedEffect |
||||
import androidx.compose.runtime.getValue |
||||
import core.ComposeBirdGame |
||||
import core.Game |
||||
import data.GameFrame |
||||
import kotlinx.browser.document |
||||
import kotlinx.browser.window |
||||
import kotlinx.coroutines.delay |
||||
import org.jetbrains.compose.web.attributes.InputType |
||||
import org.jetbrains.compose.web.attributes.disabled |
||||
import org.jetbrains.compose.web.css.marginTop |
||||
import org.jetbrains.compose.web.css.px |
||||
import org.jetbrains.compose.web.dom.* |
||||
import org.jetbrains.compose.web.renderComposable |
||||
import org.w3c.dom.HTMLElement |
||||
import org.w3c.dom.events.KeyboardEvent |
||||
import org.w3c.dom.get |
||||
|
||||
fun main() { |
||||
|
||||
val game: Game = ComposeBirdGame() |
||||
|
||||
val body = document.getElementsByTagName("body")[0] as HTMLElement |
||||
|
||||
// Enabling keyboard control |
||||
body.addEventListener("keyup", { |
||||
when ((it as KeyboardEvent).keyCode) { |
||||
38 -> { // Arrow up |
||||
game.moveBirdUp() |
||||
} |
||||
} |
||||
}) |
||||
|
||||
renderComposable(rootElementId = "root") { |
||||
|
||||
Div( |
||||
attrs = { |
||||
style { |
||||
property("text-align", "center") |
||||
} |
||||
} |
||||
) { |
||||
|
||||
// The current frame! |
||||
val gameFrame by game.gameFrame |
||||
|
||||
// Igniting the game loop |
||||
LaunchedEffect(Unit) { |
||||
while (!gameFrame.isGameOver) { |
||||
delay(60) |
||||
game.step() |
||||
} |
||||
} |
||||
|
||||
Header(gameFrame) |
||||
|
||||
Div( |
||||
attrs = { |
||||
style { |
||||
marginTop(30.px) |
||||
} |
||||
} |
||||
) { |
||||
if (gameFrame.isGameOver || gameFrame.isGameWon) { |
||||
GameResult(gameFrame) |
||||
} else { |
||||
// Play area |
||||
repeat(ComposeBirdGame.ROWS) { rowIndex -> |
||||
Div { |
||||
repeat(ComposeBirdGame.COLUMNS) { columnIndex -> |
||||
Input( |
||||
InputType.Radio, |
||||
|
||||
attrs = { |
||||
val tube = gameFrame.tubes.find { it.position == columnIndex } |
||||
val isTube = tube?.coordinates?.get(rowIndex) ?: false |
||||
val isBird = |
||||
!isTube && columnIndex == ComposeBirdGame.BIRD_COLUMN && rowIndex == gameFrame.birdPos |
||||
|
||||
// if it's either a tube node or bird, check it |
||||
checked(isTube || isBird) |
||||
|
||||
if (!isBird) { |
||||
// if it's a bird, enable it. (to change to blue color) |
||||
disabled() |
||||
} |
||||
|
||||
|
||||
} |
||||
) |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
} |
||||
|
||||
} |
||||
} |
||||
|
||||
@Composable |
||||
private fun Header(gameFrame: GameFrame) { |
||||
// Game title |
||||
H1 { |
||||
Text(value = "🐦 Wasm Bird!") |
||||
} |
||||
|
||||
// Game score |
||||
Text(value = "Your Score: ${gameFrame.score} || Top Score: ${ComposeBirdGame.TOTAL_TUBES}") |
||||
} |
||||
|
||||
@Composable |
||||
private fun GameResult(gameFrame: GameFrame) { |
||||
// Game Status |
||||
H2 { |
||||
if (gameFrame.isGameWon) { |
||||
Text("🚀 Wasm the game! 🚀") |
||||
} else { |
||||
// core.Game over |
||||
Text("💀 Wasm Over 💀") |
||||
} |
||||
} |
||||
|
||||
// Try Again |
||||
Button( |
||||
attrs = { |
||||
onClick { |
||||
window.location.reload() |
||||
} |
||||
} |
||||
) { |
||||
Text("Try Again!") |
||||
} |
||||
} |
@ -0,0 +1,17 @@
|
||||
<!DOCTYPE html> |
||||
<html lang="en"> |
||||
<head> |
||||
<meta charset="UTF-8"> |
||||
<title>compose-bird</title> |
||||
<style> |
||||
input[type=radio]{ |
||||
width:25px; |
||||
height:25px; |
||||
} |
||||
</style> |
||||
</head> |
||||
<body> |
||||
<div id="root"></div> |
||||
<script type="module" src="web-compose-bird-wasm.mjs"></script> |
||||
</body> |
||||
</html> |
@ -1 +1 @@
|
||||
kotlin.version=1.7.10 |
||||
kotlin.version=1.8.255-SNAPSHOT |
||||
|
@ -1,71 +1,3 @@
|
||||
/* |
||||
* 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 |
||||
|
||||
operator fun <T: CSSUnit> CSSSizeValue<T>.times(num: Number): CSSSizeValue<T> = CSSUnitValueTyped(value * num.toFloat(), unit) |
||||
operator fun <T: CSSUnit> Number.times(unit: CSSSizeValue<T>): CSSSizeValue<T> = CSSUnitValueTyped(unit.value * toFloat(), unit.unit) |
||||
|
||||
operator fun <T: CSSUnit> CSSSizeValue<T>.div(num: Number): CSSSizeValue<T> = CSSUnitValueTyped(value / num.toFloat(), unit) |
||||
|
||||
operator fun <T: CSSUnit> CSSSizeValue<T>.plus(b: CSSSizeValue<T>): CSSSizeValue<T> = CSSUnitValueTyped(value + b.value, unit) |
||||
operator fun <T: CSSUnit> CSSSizeValue<T>.minus(b: CSSSizeValue<T>): CSSSizeValue<T> = CSSUnitValueTyped(value - b.value, unit) |
||||
operator fun <T: CSSUnit> CSSSizeValue<T>.unaryMinus(): CSSSizeValue<T> = CSSUnitValueTyped(-value, unit) |
||||
operator fun <T: CSSUnit> CSSSizeValue<T>.unaryPlus(): CSSSizeValue<T> = CSSUnitValueTyped(value, unit) |
||||
|
||||
external interface CSSCalcOperation<T : CSSUnit>: CSSNumericValue<T> |
||||
|
||||
data class CSSCalcValue<T : CSSUnit>( |
||||
var op: CSSCalcOperation<out T> |
||||
) : CSSCalcOperation<T> { |
||||
override fun toString(): String = "calc$op" |
||||
} |
||||
|
||||
private data class CSSPlus<T : CSSUnit>( |
||||
var l: CSSNumericValue<out T>, |
||||
var r: CSSNumericValue<out T> |
||||
) : CSSCalcOperation<T> { |
||||
override fun toString(): String = "($l + $r)" |
||||
} |
||||
|
||||
private data class CSSMinus<T : CSSUnit>( |
||||
var l: CSSNumericValue<out T>, |
||||
var r: CSSNumericValue<out T> |
||||
) : CSSCalcOperation<T> { |
||||
override fun toString(): String = "($l - $r)" |
||||
} |
||||
|
||||
private data class CSSTimes<T : CSSUnit>( |
||||
var l: CSSNumericValue<out T>, |
||||
var r: Number, |
||||
val left: Boolean = true |
||||
) : CSSCalcOperation<T> { |
||||
override fun toString(): String = if (left) "($l * $r)" else "($r * $l)" |
||||
} |
||||
|
||||
private data class CSSDiv<T : CSSUnit>( |
||||
var l: CSSNumericValue<out T>, |
||||
var r: Number |
||||
) : CSSCalcOperation<T> { |
||||
override fun toString(): String = "($l / $r)" |
||||
} |
||||
|
||||
operator fun <T: CSSUnit> CSSNumericValue<out T>.plus(b: CSSNumericValue<out T>): CSSCalcValue<T> = CSSCalcValue(CSSPlus(this, b)) |
||||
operator fun <T: CSSUnit> CSSCalcValue<out T>.plus(b: CSSNumericValue<out T>): CSSCalcValue<T> = CSSCalcValue(CSSPlus(this.op, b)) |
||||
operator fun <T: CSSUnit> CSSNumericValue<out T>.plus(b: CSSCalcValue<out T>): CSSCalcValue<T> = CSSCalcValue(CSSPlus(this, b.op)) |
||||
|
||||
operator fun <T: CSSUnit> CSSNumericValue<out T>.minus(b: CSSNumericValue<out T>): CSSCalcValue<T> = CSSCalcValue(CSSMinus(this, b)) |
||||
operator fun <T: CSSUnit> CSSCalcValue<out T>.minus(b: CSSNumericValue<out T>): CSSCalcValue<T> = CSSCalcValue(CSSMinus(this.op, b)) |
||||
operator fun <T: CSSUnit> CSSNumericValue<out T>.minus(b: CSSCalcValue<out T>): CSSCalcValue<T> = CSSCalcValue(CSSMinus(this, b.op)) |
||||
|
||||
operator fun <T: CSSUnit> CSSCalcValue<out T>.times(b: Number): CSSCalcValue<T> = CSSCalcValue(CSSTimes(this.op, b)) |
||||
operator fun <T: CSSUnit> Number.times(b: CSSCalcValue<out T>): CSSCalcValue<T> = CSSCalcValue(CSSTimes(b.op, this, false)) |
||||
|
||||
operator fun <T: CSSUnit> CSSNumericValue<T>.div(b: Number): CSSCalcValue<T> = CSSCalcValue(CSSDiv(this, b)) |
||||
operator fun <T: CSSUnit> CSSCalcValue<out T>.div(b: Number): CSSCalcValue<T> = CSSCalcValue(CSSDiv(this.op, b)) |
||||
|
||||
operator fun <T: CSSUnit> CSSNumericValue<T>.times(b: Number): CSSCalcValue<T> = CSSCalcValue(CSSTimes(this, b)) |
||||
operator fun <T: CSSUnit> Number.times(b: CSSNumericValue<T>): CSSCalcValue<T> = CSSCalcValue(CSSTimes(b, this, false)) |
||||
|
||||
actual external interface CSSCalcOperation<T : CSSUnit>: CSSNumericValue<T> |
@ -1,198 +1,3 @@
|
||||
@file:Suppress("unused", "MemberVisibilityCanBePrivate") |
||||
|
||||
package org.jetbrains.compose.web.css |
||||
|
||||
external interface CSSColorValue : StylePropertyValue, CSSVariableValueAs<CSSColorValue> |
||||
|
||||
object Color { |
||||
|
||||
@Deprecated("use org.jetbrains.compose.web.css.rgb", ReplaceWith("rgb(r, g, b)")) |
||||
data class RGB(val r: Number, val g: Number, val b: Number) : CSSColorValue { |
||||
override fun toString(): String = "rgb($r, $g, $b)" |
||||
} |
||||
|
||||
@Deprecated("use org.jetbrains.compose.web.css.rgba", ReplaceWith("rgba(r, g, b, a)")) |
||||
data class RGBA(val r: Number, val g: Number, val b: Number, val a: Number) : CSSColorValue { |
||||
override fun toString(): String = "rgba($r, $g, $b, $a)" |
||||
} |
||||
|
||||
@Deprecated("use org.jetbrains.compose.web.css.hsl", ReplaceWith("hsl(h, s, l)")) |
||||
data class HSL(val h: CSSAngleValue, val s: Number, val l: Number) : CSSColorValue { |
||||
constructor(h: Number, s: Number, l: Number) : this(h.deg, s, l) |
||||
|
||||
override fun toString(): String = "hsl($h, $s%, $l%)" |
||||
} |
||||
|
||||
@Deprecated("use org.jetbrains.compose.web.css.hsla", ReplaceWith("hsla(h, s, l, a)")) |
||||
data class HSLA(val h: CSSAngleValue, val s: Number, val l: Number, val a: Number) : CSSColorValue { |
||||
constructor(h: Number, s: Number, l: Number, a: Number) : this(h.deg, s, l, a) |
||||
|
||||
override fun toString(): String = "hsla($h, $s%, $l%, $a)" |
||||
} |
||||
|
||||
inline val aliceblue get() = Color("aliceblue") |
||||
inline val antiquewhite get() = Color("antiquewhite") |
||||
inline val aquamarine get() = Color("aquamarine") |
||||
inline val azure get() = Color("azure") |
||||
inline val beige get() = Color("beige") |
||||
inline val bisque get() = Color("bisque") |
||||
inline val black get() = Color("black") |
||||
inline val blanchedalmond get() = Color("blanchedalmond") |
||||
inline val blue get() = Color("blue") |
||||
inline val blueviolet get() = Color("blueviolet") |
||||
inline val brown get() = Color("brown") |
||||
inline val burlywood get() = Color("burlywood") |
||||
inline val cadetblue get() = Color("cadetblue") |
||||
inline val chartreuse get() = Color("chartreuse") |
||||
inline val chocolate get() = Color("chocolate") |
||||
inline val cornflowerblue get() = Color("cornflowerblue") |
||||
inline val cornsilk get() = Color("cornsilk") |
||||
inline val crimson get() = Color("crimson") |
||||
inline val cyan get() = Color("cyan") |
||||
inline val darkblue get() = Color("darkblue") |
||||
inline val darkcyan get() = Color("darkcyan") |
||||
inline val darkgoldenrod get() = Color("darkgoldenrod") |
||||
inline val darkgray get() = Color("darkgray") |
||||
inline val darkgreen get() = Color("darkgreen") |
||||
inline val darkkhaki get() = Color("darkkhaki") |
||||
inline val darkmagenta get() = Color("darkmagenta") |
||||
inline val darkolivegreen get() = Color("darkolivegreen") |
||||
inline val darkorange get() = Color("darkorange") |
||||
inline val darkorchid get() = Color("darkorchid") |
||||
inline val darkred get() = Color("darkred") |
||||
inline val darksalmon get() = Color("darksalmon") |
||||
inline val darkslateblue get() = Color("darkslateblue") |
||||
inline val darkslategray get() = Color("darkslategray") |
||||
inline val darkturquoise get() = Color("darkturquoise") |
||||
inline val darkviolet get() = Color("darkviolet") |
||||
inline val deeppink get() = Color("deeppink") |
||||
inline val deepskyblue get() = Color("deepskyblue") |
||||
inline val dimgray get() = Color("dimgray") |
||||
inline val dodgerblue get() = Color("dodgerblue") |
||||
inline val firebrick get() = Color("firebrick") |
||||
inline val floralwhite get() = Color("floralwhite") |
||||
inline val forestgreen get() = Color("forestgreen") |
||||
inline val fuchsia get() = Color("fuchsia") |
||||
inline val gainsboro get() = Color("gainsboro") |
||||
inline val ghostwhite get() = Color("ghostwhite") |
||||
inline val goldenrod get() = Color("goldenrod") |
||||
inline val gold get() = Color("gold") |
||||
inline val gray get() = Color("gray") |
||||
inline val green get() = Color("green") |
||||
inline val greenyellow get() = Color("greenyellow") |
||||
inline val honeydew get() = Color("honeydew") |
||||
inline val hotpink get() = Color("hotpink") |
||||
inline val indianred get() = Color("indianred") |
||||
inline val indigo get() = Color("indigo") |
||||
inline val ivory get() = Color("ivory") |
||||
inline val khaki get() = Color("khaki") |
||||
inline val lavenderblush get() = Color("lavenderblush") |
||||
inline val lavender get() = Color("lavender") |
||||
inline val lawngreen get() = Color("lawngreen") |
||||
inline val lemonchiffon get() = Color("lemonchiffon") |
||||
inline val lightblue get() = Color("lightblue") |
||||
inline val lightcoral get() = Color("lightcoral") |
||||
inline val lightcyan get() = Color("lightcyan") |
||||
inline val lightgoldenrodyellow get() = Color("lightgoldenrodyellow") |
||||
inline val lightgray get() = Color("lightgray") |
||||
inline val lightgreen get() = Color("lightgreen") |
||||
inline val lightpink get() = Color("lightpink") |
||||
inline val lightsalmon get() = Color("lightsalmon") |
||||
inline val lightseagreen get() = Color("lightseagreen") |
||||
inline val lightskyblue get() = Color("lightskyblue") |
||||
inline val lightslategray get() = Color("lightslategray") |
||||
inline val lightsteelblue get() = Color("lightsteelblue") |
||||
inline val lightyellow get() = Color("lightyellow") |
||||
inline val limegreen get() = Color("limegreen") |
||||
inline val lime get() = Color("lime") |
||||
inline val linen get() = Color("linen") |
||||
inline val magenta get() = Color("magenta") |
||||
inline val maroon get() = Color("maroon") |
||||
inline val mediumaquamarine get() = Color("mediumaquamarine") |
||||
inline val mediumblue get() = Color("mediumblue") |
||||
inline val mediumorchid get() = Color("mediumorchid") |
||||
inline val mediumpurple get() = Color("mediumpurple") |
||||
inline val mediumseagreen get() = Color("mediumseagreen") |
||||
inline val mediumslateblue get() = Color("mediumslateblue") |
||||
inline val mediumspringgreen get() = Color("mediumspringgreen") |
||||
inline val mediumturquoise get() = Color("mediumturquoise") |
||||
inline val mediumvioletred get() = Color("mediumvioletred") |
||||
inline val midnightblue get() = Color("midnightblue") |
||||
inline val mintcream get() = Color("mintcream") |
||||
inline val mistyrose get() = Color("mistyrose") |
||||
inline val moccasin get() = Color("moccasin") |
||||
inline val navajowhite get() = Color("navajowhite") |
||||
inline val navi get() = Color("navi") |
||||
inline val oldlace get() = Color("oldlace") |
||||
inline val olivedrab get() = Color("olivedrab") |
||||
inline val olive get() = Color("olive") |
||||
inline val orange get() = Color("orange") |
||||
inline val orangered get() = Color("orangered") |
||||
inline val orchid get() = Color("orchid") |
||||
inline val palegoldenrod get() = Color("palegoldenrod") |
||||
inline val palegreen get() = Color("palegreen") |
||||
inline val paleturquoise get() = Color("paleturquoise") |
||||
inline val palevioletred get() = Color("palevioletred") |
||||
inline val papayawhip get() = Color("papayawhip") |
||||
inline val peachpuff get() = Color("peachpuff") |
||||
inline val peru get() = Color("peru") |
||||
inline val pink get() = Color("pink") |
||||
inline val plum get() = Color("plum") |
||||
inline val powderblue get() = Color("powderblue") |
||||
inline val purple get() = Color("purple") |
||||
inline val rebeccapurple get() = Color("rebeccapurple") |
||||
inline val red get() = Color("red") |
||||
inline val rosybrown get() = Color("rosybrown") |
||||
inline val royalblue get() = Color("royalblue") |
||||
inline val saddlebrown get() = Color("saddlebrown") |
||||
inline val salmon get() = Color("salmon") |
||||
inline val sandybrown get() = Color("sandybrown") |
||||
inline val seagreen get() = Color("seagreen") |
||||
inline val seashell get() = Color("seashell") |
||||
inline val sienna get() = Color("sienna") |
||||
inline val silver get() = Color("silver") |
||||
inline val skyblue get() = Color("skyblue") |
||||
inline val slateblue get() = Color("slateblue") |
||||
inline val slategray get() = Color("slategray") |
||||
inline val snow get() = Color("snow") |
||||
inline val springgreen get() = Color("springgreen") |
||||
inline val steelblue get() = Color("steelblue") |
||||
inline val teal get() = Color("teal") |
||||
inline val thistle get() = Color("thistle") |
||||
inline val tomato get() = Color("tomato") |
||||
inline val turquoise get() = Color("turquoise") |
||||
inline val violet get() = Color("violet") |
||||
inline val wheat get() = Color("wheat") |
||||
inline val white get() = Color("white") |
||||
inline val whitesmoke get() = Color("whitesmoke") |
||||
inline val yellowgreen get() = Color("yellowgreen") |
||||
inline val yellow get() = Color("yellow") |
||||
|
||||
inline val transparent get() = Color("transparent") |
||||
inline val currentColor get() = Color("currentColor") |
||||
} |
||||
|
||||
fun Color(name: String): CSSColorValue = name.unsafeCast<CSSColorValue>() |
||||
|
||||
private class RGB(val r: Number, val g: Number, val b: Number): CSSColorValue { |
||||
override fun toString(): String = "rgb($r, $g, $b)" |
||||
} |
||||
|
||||
private class RGBA(val r: Number, val g: Number, val b: Number, val a: Number) : CSSColorValue { |
||||
override fun toString(): String = "rgba($r, $g, $b, $a)" |
||||
} |
||||
|
||||
private class HSL(val h: CSSAngleValue, val s: Number, val l: Number) : CSSColorValue { |
||||
override fun toString(): String = "hsl($h, $s%, $l%)" |
||||
} |
||||
|
||||
private class HSLA(val h: CSSAngleValue, val s: Number, val l: Number, val a: Number) : CSSColorValue { |
||||
override fun toString(): String = "hsla($h, $s%, $l%, $a)" |
||||
} |
||||
|
||||
fun rgb(r: Number, g: Number, b: Number): CSSColorValue = RGB(r, g, b) |
||||
fun rgba(r: Number, g: Number, b: Number, a: Number): CSSColorValue = RGBA(r, g, b, a) |
||||
fun hsl(h: CSSAngleValue, s: Number, l: Number): CSSColorValue = HSL(h, s, l) |
||||
fun hsl(h: Number, s: Number, l: Number): CSSColorValue = HSL(h.deg, s, l) |
||||
fun hsla(h: CSSAngleValue, s: Number, l: Number, a: Number): CSSColorValue = HSLA(h, s, l, a) |
||||
fun hsla(h: Number, s: Number, l: Number, a: Number): CSSColorValue = HSLA(h.deg, s, l, a) |
||||
actual external interface CSSColorValue : StylePropertyValue, CSSVariableValueAs<CSSColorValue> |
@ -1,195 +1,3 @@
|
||||
/* |
||||
* 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. |
||||
*/ |
||||
|
||||
@file:Suppress("NOTHING_TO_INLINE", "unused") |
||||
|
||||
package org.jetbrains.compose.web.css |
||||
|
||||
import org.jetbrains.compose.web.attributes.HtmlAttrMarker |
||||
import org.jetbrains.compose.web.internal.runtime.ComposeWebInternalApi |
||||
import kotlin.properties.ReadOnlyProperty |
||||
|
||||
@Deprecated( |
||||
message = "Renamed to StyleScope", |
||||
replaceWith = ReplaceWith("StyleScope", "org.jetbrains.compose.web.css.StyleScope") |
||||
) |
||||
typealias StyleBuilder = StyleScope |
||||
|
||||
/** |
||||
* StyleScope serves for two main purposes. Passed as a builder context (in [AttrsScope]), it |
||||
* makes it possible to: |
||||
* 1. Add inlined css properties to the element (@see [property]) |
||||
* 2. Set values to CSS variables (@see [variable]) |
||||
*/ |
||||
@HtmlAttrMarker |
||||
interface StyleScope { |
||||
/** |
||||
* Adds arbitrary CSS property to the inline style of the element |
||||
* @param propertyName - the name of css property as [per spec](https://developer.mozilla.org/en-US/docs/Web/CSS/Reference) |
||||
* @param value - the value, it can be either String or specialized type like [CSSNumeric] or [CSSColorValue] |
||||
* |
||||
* Most frequent CSS property values can be set via specialized methods, like [width], [display] etc. |
||||
* |
||||
* Example: |
||||
* ``` |
||||
* Div({ |
||||
* style { |
||||
* property("some-exotic-css-property", "I am a string value") |
||||
* property("some-exotic-css-property-width", 5.px) |
||||
* } |
||||
* }) |
||||
* ``` |
||||
*/ |
||||
fun property(propertyName: String, value: StylePropertyValue) |
||||
fun variable(variableName: String, value: StylePropertyValue) |
||||
|
||||
fun property(propertyName: String, value: String) = property(propertyName, StylePropertyValue(value)) |
||||
fun property(propertyName: String, value: Number) = property(propertyName, StylePropertyValue(value)) |
||||
fun variable(variableName: String, value: String) = variable(variableName, StylePropertyValue(value)) |
||||
fun variable(variableName: String, value: Number) = variable(variableName, StylePropertyValue(value)) |
||||
|
||||
operator fun <TValue : StylePropertyValue> CSSStyleVariable<TValue>.invoke(value: TValue) { |
||||
variable(name, value.toString()) |
||||
} |
||||
|
||||
operator fun CSSStyleVariable<StylePropertyString>.invoke(value: String) { |
||||
variable(name, value) |
||||
} |
||||
|
||||
operator fun CSSStyleVariable<StylePropertyNumber>.invoke(value: Number) { |
||||
variable(name, value) |
||||
} |
||||
} |
||||
|
||||
internal inline fun variableValue(variableName: String, fallback: StylePropertyValue? = null) = |
||||
"var(--$variableName${fallback?.let { ", $it" } ?: ""})" |
||||
|
||||
external interface CSSVariableValueAs<out T : StylePropertyValue> |
||||
|
||||
inline fun <TValue> CSSVariableValue(value: StylePropertyValue) = |
||||
value.unsafeCast<TValue>() |
||||
|
||||
inline fun <TValue> CSSVariableValue(value: String) = |
||||
CSSVariableValue<TValue>(StylePropertyValue(value)) |
||||
|
||||
// after adding `variable` word `add` became ambiguous |
||||
@Deprecated( |
||||
"use property instead, will remove it soon", |
||||
ReplaceWith("property(propertyName, value)") |
||||
) |
||||
fun StyleScope.add( |
||||
propertyName: String, |
||||
value: StylePropertyValue |
||||
) = property(propertyName, value) |
||||
|
||||
interface CSSVariable { |
||||
val name: String |
||||
} |
||||
|
||||
class CSSStyleVariable<out TValue : StylePropertyValue>(override val name: String) : CSSVariable |
||||
|
||||
fun <TValue : StylePropertyValue> CSSStyleVariable<TValue>.value(fallback: TValue? = null) = |
||||
CSSVariableValue<TValue>( |
||||
variableValue( |
||||
name, |
||||
fallback |
||||
) |
||||
) |
||||
|
||||
fun <TValue> CSSStyleVariable<TValue>.value(fallback: TValue? = null) |
||||
where TValue : CSSVariableValueAs<TValue>, |
||||
TValue : StylePropertyValue = |
||||
CSSVariableValue<TValue>( |
||||
variableValue( |
||||
name, |
||||
fallback |
||||
) |
||||
) |
||||
|
||||
/** |
||||
* Introduces CSS variable that can be later referred anywhere in [StyleSheet] |
||||
* |
||||
* Example: |
||||
* ``` |
||||
* object AppCSSVariables { |
||||
* val width by variable<CSSUnitValue>() |
||||
* val stringHeight by variable<StylePropertyString>() |
||||
* val order by variable<StylePropertyNumber>() |
||||
* } |
||||
* |
||||
* object AppStylesheet : StyleSheet() { |
||||
* val classWithProperties by style { |
||||
* AppCSSVariables.width(100.px) |
||||
* property("width", AppCSSVariables.width.value()) |
||||
* } |
||||
*``` |
||||
* |
||||
*/ |
||||
fun <TValue : StylePropertyValue> variable() = |
||||
ReadOnlyProperty<Any?, CSSStyleVariable<TValue>> { _, property -> |
||||
CSSStyleVariable(property.name) |
||||
} |
||||
|
||||
interface StyleHolder { |
||||
@ComposeWebInternalApi |
||||
val properties: StylePropertyList |
||||
@ComposeWebInternalApi |
||||
val variables: StylePropertyList |
||||
} |
||||
|
||||
@Deprecated( |
||||
message = "Renamed to StyleScopeBuilder", |
||||
replaceWith = ReplaceWith("StyleScopeBuilder", "org.jetbrains.compose.web.css.StyleScopeBuilder") |
||||
) |
||||
typealias StyleBuilderImpl = StyleScopeBuilder |
||||
|
||||
@Suppress("EqualsOrHashCode") |
||||
open class StyleScopeBuilder : StyleScope, StyleHolder { |
||||
override val properties: MutableStylePropertyList = mutableListOf() |
||||
override val variables: MutableStylePropertyList = mutableListOf() |
||||
|
||||
override fun property(propertyName: String, value: StylePropertyValue) { |
||||
properties.add(StylePropertyDeclaration(propertyName, value)) |
||||
} |
||||
|
||||
override fun variable(variableName: String, value: StylePropertyValue) { |
||||
variables.add(StylePropertyDeclaration(variableName, value)) |
||||
} |
||||
|
||||
// StylePropertyValue is js native object without equals |
||||
override fun equals(other: Any?): Boolean { |
||||
return if (other is StyleHolder) { |
||||
properties.nativeEquals(other.properties) && |
||||
variables.nativeEquals(other.variables) |
||||
} else false |
||||
} |
||||
|
||||
@ComposeWebInternalApi |
||||
internal fun copyFrom(sb: StyleHolder) { |
||||
properties.addAll(sb.properties) |
||||
variables.addAll(sb.variables) |
||||
} |
||||
} |
||||
|
||||
data class StylePropertyDeclaration( |
||||
val name: String, |
||||
val value: StylePropertyValue |
||||
) { |
||||
constructor(name: String, value: String) : this(name, value.unsafeCast<StylePropertyValue>()) |
||||
constructor(name: String, value: Number) : this(name, value.unsafeCast<StylePropertyValue>()) |
||||
} |
||||
typealias StylePropertyList = List<StylePropertyDeclaration> |
||||
typealias MutableStylePropertyList = MutableList<StylePropertyDeclaration> |
||||
|
||||
internal fun StylePropertyList.nativeEquals(properties: StylePropertyList): Boolean { |
||||
if (this.size != properties.size) return false |
||||
|
||||
var index = 0 |
||||
return all { prop -> |
||||
val otherProp = properties[index++] |
||||
prop.name == otherProp.name && |
||||
prop.value.toString() == otherProp.value.toString() |
||||
} |
||||
} |
||||
actual external interface CSSVariableValueAs<out T : StylePropertyValue> |
@ -0,0 +1,54 @@
|
||||
package org.jetbrains.compose.web |
||||
|
||||
import org.w3c.dom.events.* |
||||
import org.w3c.dom.css.CSSRule |
||||
import androidx.compose.web.events.* |
||||
import org.jetbrains.compose.web.css.CSSStyleValue |
||||
import org.w3c.dom.HTMLElement |
||||
import org.w3c.dom.svg.SVGElement |
||||
import org.jetbrains.compose.web.css.StylePropertyValue |
||||
import org.jetbrains.compose.web.dom.RadioGroupScope |
||||
import org.jetbrains.compose.web.dom.ElementBuilder |
||||
import org.w3c.dom.Element |
||||
|
||||
@PublishedApi |
||||
internal actual fun <T> SyntheticEvent<*>.unsafeCast(): T = asDynamic().unsafeCast<T>() |
||||
@PublishedApi |
||||
internal actual fun <T> CSSRule.unsafeCast(): T = asDynamic().unsafeCast<T>() |
||||
@PublishedApi |
||||
internal actual fun <T> CSSStyleValue.unsafeCast(): T = asDynamic().unsafeCast<T>() |
||||
@PublishedApi |
||||
internal actual fun <T> Event.unsafeCast(): T = asDynamic().unsafeCast<T>() |
||||
@PublishedApi |
||||
internal actual fun <T> EventTarget.unsafeCast(): T = asDynamic().unsafeCast<T>() |
||||
@PublishedApi |
||||
internal actual fun <T> String.unsafeCast(): T = asDynamic().unsafeCast<T>() |
||||
@PublishedApi |
||||
internal actual fun <T> Number.unsafeCast(): T = asDynamic().unsafeCast<T>() |
||||
@PublishedApi |
||||
internal actual fun <T> HTMLElement.unsafeCast(): T = asDynamic().unsafeCast<T>() |
||||
@PublishedApi |
||||
internal actual fun <T> SVGElement.unsafeCast(): T = asDynamic().unsafeCast<T>() |
||||
@PublishedApi |
||||
internal actual fun <T> StylePropertyValue.unsafeCast(): T = asDynamic().unsafeCast<T>() |
||||
@PublishedApi |
||||
@ExperimentalComposeWebApi |
||||
internal actual fun <T> RadioGroupScope<*>.unsafeCast(): T = asDynamic().unsafeCast<T>() |
||||
@PublishedApi |
||||
internal actual fun <T> ElementBuilder<*>.unsafeCast(): T = asDynamic().unsafeCast<T>() |
||||
|
||||
@PublishedApi |
||||
internal actual fun Any.unsafeCastBoolean(): Boolean = asDynamic().unsafeCast<Boolean>() |
||||
@PublishedApi |
||||
internal actual fun Any.unsafeCastString(): String = asDynamic().unsafeCast<String>() |
||||
|
||||
@PublishedApi |
||||
internal actual fun Any.getStringProperty(name: String): String? = asDynamic()[name] as String? |
||||
@PublishedApi |
||||
internal actual fun Any.getBooleanProperty(name: String): Boolean? = asDynamic()[name] as Boolean? |
||||
@PublishedApi |
||||
internal actual fun Any.getIntProperty(name: String): Int? = asDynamic()[name] as Int? |
||||
@PublishedApi |
||||
internal actual fun <T> Any.getAnyProperty(name: String): T = asDynamic()[name].unsafeCast<T>() |
||||
|
||||
internal actual fun Element.getAttributeNamesWorkaround(): Array<String> = getAttributeNames() |
@ -0,0 +1,14 @@
|
||||
/* |
||||
* 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. |
||||
*/ |
||||
|
||||
@file:Suppress("NOTHING_TO_INLINE") |
||||
|
||||
package org.jetbrains.compose.web.css |
||||
|
||||
import org.jetbrains.compose.web.* |
||||
|
||||
expect interface CSSKeywordValue : CSSStyleValue |
||||
|
||||
inline fun CSSKeywordValue(value: String): CSSKeywordValue = CSSStyleValue(value).unsafeCast<CSSKeywordValue>() |
@ -0,0 +1,71 @@
|
||||
/* |
||||
* 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 |
||||
|
||||
operator fun <T: CSSUnit> CSSSizeValue<T>.times(num: Number): CSSSizeValue<T> = CSSUnitValueTyped(value * num.toFloat(), unit) |
||||
operator fun <T: CSSUnit> Number.times(unit: CSSSizeValue<T>): CSSSizeValue<T> = CSSUnitValueTyped(unit.value * toFloat(), unit.unit) |
||||
|
||||
operator fun <T: CSSUnit> CSSSizeValue<T>.div(num: Number): CSSSizeValue<T> = CSSUnitValueTyped(value / num.toFloat(), unit) |
||||
|
||||
operator fun <T: CSSUnit> CSSSizeValue<T>.plus(b: CSSSizeValue<T>): CSSSizeValue<T> = CSSUnitValueTyped(value + b.value, unit) |
||||
operator fun <T: CSSUnit> CSSSizeValue<T>.minus(b: CSSSizeValue<T>): CSSSizeValue<T> = CSSUnitValueTyped(value - b.value, unit) |
||||
operator fun <T: CSSUnit> CSSSizeValue<T>.unaryMinus(): CSSSizeValue<T> = CSSUnitValueTyped(-value, unit) |
||||
operator fun <T: CSSUnit> CSSSizeValue<T>.unaryPlus(): CSSSizeValue<T> = CSSUnitValueTyped(value, unit) |
||||
|
||||
expect interface CSSCalcOperation<T : CSSUnit>: CSSNumericValue<T> |
||||
|
||||
data class CSSCalcValue<T : CSSUnit>( |
||||
var op: CSSCalcOperation<out T> |
||||
) : CSSCalcOperation<T> { |
||||
override fun toString(): String = "calc$op" |
||||
} |
||||
|
||||
private data class CSSPlus<T : CSSUnit>( |
||||
var l: CSSNumericValue<out T>, |
||||
var r: CSSNumericValue<out T> |
||||
) : CSSCalcOperation<T> { |
||||
override fun toString(): String = "($l + $r)" |
||||
} |
||||
|
||||
private data class CSSMinus<T : CSSUnit>( |
||||
var l: CSSNumericValue<out T>, |
||||
var r: CSSNumericValue<out T> |
||||
) : CSSCalcOperation<T> { |
||||
override fun toString(): String = "($l - $r)" |
||||
} |
||||
|
||||
private data class CSSTimes<T : CSSUnit>( |
||||
var l: CSSNumericValue<out T>, |
||||
var r: Number, |
||||
val left: Boolean = true |
||||
) : CSSCalcOperation<T> { |
||||
override fun toString(): String = if (left) "($l * $r)" else "($r * $l)" |
||||
} |
||||
|
||||
private data class CSSDiv<T : CSSUnit>( |
||||
var l: CSSNumericValue<out T>, |
||||
var r: Number |
||||
) : CSSCalcOperation<T> { |
||||
override fun toString(): String = "($l / $r)" |
||||
} |
||||
|
||||
operator fun <T: CSSUnit> CSSNumericValue<out T>.plus(b: CSSNumericValue<out T>): CSSCalcValue<T> = CSSCalcValue(CSSPlus(this, b)) |
||||
operator fun <T: CSSUnit> CSSCalcValue<out T>.plus(b: CSSNumericValue<out T>): CSSCalcValue<T> = CSSCalcValue(CSSPlus(this.op, b)) |
||||
operator fun <T: CSSUnit> CSSNumericValue<out T>.plus(b: CSSCalcValue<out T>): CSSCalcValue<T> = CSSCalcValue(CSSPlus(this, b.op)) |
||||
|
||||
operator fun <T: CSSUnit> CSSNumericValue<out T>.minus(b: CSSNumericValue<out T>): CSSCalcValue<T> = CSSCalcValue(CSSMinus(this, b)) |
||||
operator fun <T: CSSUnit> CSSCalcValue<out T>.minus(b: CSSNumericValue<out T>): CSSCalcValue<T> = CSSCalcValue(CSSMinus(this.op, b)) |
||||
operator fun <T: CSSUnit> CSSNumericValue<out T>.minus(b: CSSCalcValue<out T>): CSSCalcValue<T> = CSSCalcValue(CSSMinus(this, b.op)) |
||||
|
||||
operator fun <T: CSSUnit> CSSCalcValue<out T>.times(b: Number): CSSCalcValue<T> = CSSCalcValue(CSSTimes(this.op, b)) |
||||
operator fun <T: CSSUnit> Number.times(b: CSSCalcValue<out T>): CSSCalcValue<T> = CSSCalcValue(CSSTimes(b.op, this, false)) |
||||
|
||||
operator fun <T: CSSUnit> CSSNumericValue<T>.div(b: Number): CSSCalcValue<T> = CSSCalcValue(CSSDiv(this, b)) |
||||
operator fun <T: CSSUnit> CSSCalcValue<out T>.div(b: Number): CSSCalcValue<T> = CSSCalcValue(CSSDiv(this.op, b)) |
||||
|
||||
operator fun <T: CSSUnit> CSSNumericValue<T>.times(b: Number): CSSCalcValue<T> = CSSCalcValue(CSSTimes(this, b)) |
||||
operator fun <T: CSSUnit> Number.times(b: CSSNumericValue<T>): CSSCalcValue<T> = CSSCalcValue(CSSTimes(b, this, false)) |
||||
|
@ -0,0 +1,249 @@
|
||||
@file:Suppress("Unused", "NOTHING_TO_INLINE", "NESTED_CLASS_IN_EXTERNAL_INTERFACE", "INLINE_EXTERNAL_DECLARATION", "WRONG_BODY_OF_EXTERNAL_DECLARATION", "NESTED_EXTERNAL_DECLARATION", "ClassName") |
||||
|
||||
package org.jetbrains.compose.web.css |
||||
|
||||
expect interface CSSNumericValue<T : CSSUnit> : StylePropertyValue, CSSVariableValueAs<CSSNumericValue<T>> |
||||
|
||||
expect interface CSSSizeValue<T : CSSUnit> : CSSNumericValue<T> { |
||||
val value: Float |
||||
val unit: T |
||||
} |
||||
|
||||
data class CSSUnitValueTyped<T : CSSUnit>( |
||||
override val value: Float, |
||||
override val unit: T |
||||
) : CSSSizeValue<T> { |
||||
override fun toString(): String = "$value$unit" |
||||
} |
||||
|
||||
interface CSSUnitLengthOrPercentage: CSSUnit |
||||
interface CSSUnitPercentage: CSSUnitLengthOrPercentage |
||||
interface CSSUnitLength: CSSUnitLengthOrPercentage |
||||
interface CSSUnitRel : CSSUnitLength |
||||
interface CSSUnitAbs: CSSUnitLength |
||||
interface CSSUnitAngle: CSSUnit |
||||
interface CSSUnitTime: CSSUnit |
||||
interface CSSUnitFrequency: CSSUnit |
||||
interface CSSUnitResolution: CSSUnit |
||||
interface CSSUnitFlex: CSSUnit |
||||
|
||||
typealias CSSAngleValue = CSSSizeValue<out CSSUnitAngle> |
||||
typealias CSSLengthOrPercentageValue = CSSSizeValue<out CSSUnitLengthOrPercentage> |
||||
typealias CSSLengthValue = CSSSizeValue<out CSSUnitLength> |
||||
typealias CSSPercentageValue = CSSSizeValue<out CSSUnitPercentage> |
||||
typealias CSSUnitValue = CSSSizeValue<out CSSUnit> |
||||
typealias CSSNumeric = CSSNumericValue<out CSSUnit> |
||||
typealias CSSpxValue = CSSSizeValue<CSSUnit.px> |
||||
|
||||
// fake interfaces to distinguish units |
||||
interface CSSUnit { |
||||
interface percent: CSSUnitPercentage |
||||
|
||||
interface em: CSSUnitRel |
||||
|
||||
interface ex: CSSUnitRel |
||||
|
||||
interface ch: CSSUnitRel |
||||
|
||||
interface ic: CSSUnitRel |
||||
|
||||
interface rem: CSSUnitRel |
||||
|
||||
interface lh: CSSUnitRel |
||||
|
||||
interface rlh: CSSUnitRel |
||||
|
||||
interface vw: CSSUnitRel |
||||
|
||||
interface vh: CSSUnitRel |
||||
|
||||
interface vi: CSSUnitRel |
||||
|
||||
interface vb: CSSUnitRel |
||||
|
||||
interface vmin: CSSUnitRel |
||||
|
||||
interface vmax: CSSUnitRel |
||||
|
||||
interface cm: CSSUnitRel |
||||
|
||||
interface mm: CSSUnitRel |
||||
|
||||
interface Q: CSSUnitRel |
||||
|
||||
interface pt: CSSUnitAbs |
||||
|
||||
interface pc: CSSUnitAbs |
||||
|
||||
interface px: CSSUnitAbs |
||||
|
||||
interface deg: CSSUnitAngle |
||||
|
||||
interface grad: CSSUnitAngle |
||||
|
||||
interface rad: CSSUnitAngle |
||||
|
||||
interface turn: CSSUnitAngle |
||||
|
||||
interface s: CSSUnitTime |
||||
|
||||
interface ms: CSSUnitTime |
||||
|
||||
interface Hz: CSSUnitFrequency |
||||
|
||||
interface kHz: CSSUnitFrequency |
||||
|
||||
interface dpi: CSSUnitResolution |
||||
|
||||
interface dpcm: CSSUnitResolution |
||||
|
||||
interface dppx: CSSUnitResolution |
||||
|
||||
interface fr: CSSUnitFlex |
||||
|
||||
interface number: CSSUnit |
||||
|
||||
companion object { |
||||
inline val percent get() = "%".unsafeCast<percent>() |
||||
|
||||
inline val em get() = "em".unsafeCast<em>() |
||||
|
||||
inline val ex get() = "ex".unsafeCast<ex>() |
||||
|
||||
inline val ch get() = "ch".unsafeCast<ch>() |
||||
|
||||
inline val ic get() = "ic".unsafeCast<ic>() |
||||
|
||||
inline val rem get() = "rem".unsafeCast<rem>() |
||||
|
||||
inline val lh get() = "lh".unsafeCast<lh>() |
||||
|
||||
inline val rlh get() = "rlh".unsafeCast<rlh>() |
||||
|
||||
inline val vw get() = "vw".unsafeCast<vw>() |
||||
|
||||
inline val vh get() = "vh".unsafeCast<vh>() |
||||
|
||||
inline val vi get() = "vi".unsafeCast<vi>() |
||||
|
||||
inline val vb get() = "vb".unsafeCast<vb>() |
||||
|
||||
inline val vmin get() = "vmin".unsafeCast<vmin>() |
||||
|
||||
inline val vmax get() = "vmax".unsafeCast<vmax>() |
||||
|
||||
inline val cm get() = "cm".unsafeCast<cm>() |
||||
|
||||
inline val mm get() = "mm".unsafeCast<mm>() |
||||
|
||||
inline val Q get() = "Q".unsafeCast<Q>() |
||||
|
||||
inline val pt get() = "pt".unsafeCast<pt>() |
||||
|
||||
inline val pc get() = "pc".unsafeCast<pc>() |
||||
|
||||
inline val px get() = "px".unsafeCast<px>() |
||||
|
||||
inline val deg get() = "deg".unsafeCast<deg>() |
||||
|
||||
inline val grad get() = "grad".unsafeCast<grad>() |
||||
|
||||
inline val rad get() = "rad".unsafeCast<rad>() |
||||
|
||||
inline val turn get() = "turn".unsafeCast<turn>() |
||||
|
||||
inline val s get() = "s".unsafeCast<s>() |
||||
|
||||
inline val ms get() = "ms".unsafeCast<ms>() |
||||
|
||||
inline val Hz get() = "Hz".unsafeCast<Hz>() |
||||
|
||||
inline val kHz get() = "kHz".unsafeCast<kHz>() |
||||
|
||||
inline val dpi get() = "dpi".unsafeCast<dpi>() |
||||
|
||||
inline val dpcm get() = "dpcm".unsafeCast<dpcm>() |
||||
|
||||
inline val dppx get() = "dppx".unsafeCast<dppx>() |
||||
|
||||
inline val fr get() = "fr".unsafeCast<fr>() |
||||
|
||||
inline val number get() = "number".unsafeCast<number>() |
||||
} |
||||
} |
||||
|
||||
|
||||
val Number.number |
||||
get(): CSSSizeValue<CSSUnit.number> = CSSUnitValueTyped(this.toFloat(), CSSUnit.number) |
||||
|
||||
val Number.percent |
||||
get() : CSSSizeValue<CSSUnit.percent> = CSSUnitValueTyped(this.toFloat(), CSSUnit.percent) |
||||
|
||||
val Number.em |
||||
get() : CSSSizeValue<CSSUnit.em> = CSSUnitValueTyped(this.toFloat(), CSSUnit.em) |
||||
|
||||
val Number.ex |
||||
get(): CSSSizeValue<CSSUnit.ex> = CSSUnitValueTyped(this.toFloat(), CSSUnit.ex) |
||||
|
||||
val Number.ch |
||||
get(): CSSSizeValue<CSSUnit.ch> = CSSUnitValueTyped(this.toFloat(), CSSUnit.ch) |
||||
|
||||
val Number.cssRem |
||||
get(): CSSSizeValue<CSSUnit.rem> = CSSUnitValueTyped(this.toFloat(), CSSUnit.rem) |
||||
|
||||
val Number.vw |
||||
get(): CSSSizeValue<CSSUnit.vw> = CSSUnitValueTyped(this.toFloat(), CSSUnit.vw) |
||||
|
||||
val Number.vh |
||||
get(): CSSSizeValue<CSSUnit.vh> = CSSUnitValueTyped(this.toFloat(), CSSUnit.vh) |
||||
|
||||
val Number.vmin |
||||
get(): CSSSizeValue<CSSUnit.vmin> = CSSUnitValueTyped(this.toFloat(), CSSUnit.vmin) |
||||
|
||||
val Number.vmax |
||||
get(): CSSSizeValue<CSSUnit.vmax> = CSSUnitValueTyped(this.toFloat(), CSSUnit.vmax) |
||||
|
||||
val Number.cm |
||||
get(): CSSSizeValue<CSSUnit.cm> = CSSUnitValueTyped(this.toFloat(), CSSUnit.cm) |
||||
|
||||
val Number.mm |
||||
get(): CSSSizeValue<CSSUnit.mm> = CSSUnitValueTyped(this.toFloat(), CSSUnit.mm) |
||||
|
||||
val Number.Q |
||||
get() : CSSSizeValue<CSSUnit.Q> = CSSUnitValueTyped(this.toFloat(), CSSUnit.Q) |
||||
|
||||
val Number.pt |
||||
get(): CSSSizeValue<CSSUnit.pt> = CSSUnitValueTyped(this.toFloat(), CSSUnit.pt) |
||||
val Number.pc |
||||
get(): CSSSizeValue<CSSUnit.pc> = CSSUnitValueTyped(this.toFloat(), CSSUnit.pc) |
||||
val Number.px |
||||
get(): CSSSizeValue<CSSUnit.px> = CSSUnitValueTyped(this.toFloat(), CSSUnit.px) |
||||
|
||||
val Number.deg |
||||
get(): CSSSizeValue<CSSUnit.deg> = CSSUnitValueTyped(this.toFloat(), CSSUnit.deg) |
||||
val Number.grad |
||||
get(): CSSSizeValue<CSSUnit.grad> = CSSUnitValueTyped(this.toFloat(), CSSUnit.grad) |
||||
val Number.rad |
||||
get(): CSSSizeValue<CSSUnit.rad> = CSSUnitValueTyped(this.toFloat(), CSSUnit.rad) |
||||
val Number.turn |
||||
get(): CSSSizeValue<CSSUnit.turn> = CSSUnitValueTyped(this.toFloat(), CSSUnit.turn) |
||||
|
||||
val Number.s |
||||
get(): CSSSizeValue<CSSUnit.s> = CSSUnitValueTyped(this.toFloat(), CSSUnit.s) |
||||
val Number.ms |
||||
get(): CSSSizeValue<CSSUnit.ms> = CSSUnitValueTyped(this.toFloat(), CSSUnit.ms) |
||||
|
||||
val Number.Hz |
||||
get(): CSSSizeValue<CSSUnit.Hz> = CSSUnitValueTyped(this.toFloat(), CSSUnit.Hz) |
||||
val Number.kHz |
||||
get(): CSSSizeValue<CSSUnit.kHz> = CSSUnitValueTyped(this.toFloat(), CSSUnit.kHz) |
||||
|
||||
val Number.dpi |
||||
get(): CSSSizeValue<CSSUnit.dpi> = CSSUnitValueTyped(this.toFloat(), CSSUnit.dpi) |
||||
val Number.dpcm |
||||
get(): CSSSizeValue<CSSUnit.dpcm> = CSSUnitValueTyped(this.toFloat(), CSSUnit.dpcm) |
||||
val Number.dppx |
||||
get(): CSSSizeValue<CSSUnit.dppx> = CSSUnitValueTyped(this.toFloat(), CSSUnit.dppx) |
||||
|
||||
val Number.fr |
||||
get(): CSSSizeValue<CSSUnit.fr> = CSSUnitValueTyped(this.toFloat(), CSSUnit.fr) |
@ -0,0 +1,198 @@
|
||||
@file:Suppress("unused", "MemberVisibilityCanBePrivate") |
||||
|
||||
package org.jetbrains.compose.web.css |
||||
|
||||
expect interface CSSColorValue : StylePropertyValue, CSSVariableValueAs<CSSColorValue> |
||||
|
||||
object Color { |
||||
|
||||
@Deprecated("use org.jetbrains.compose.web.css.rgb", ReplaceWith("rgb(r, g, b)")) |
||||
data class RGB(val r: Number, val g: Number, val b: Number) : CSSColorValue { |
||||
override fun toString(): String = "rgb($r, $g, $b)" |
||||
} |
||||
|
||||
@Deprecated("use org.jetbrains.compose.web.css.rgba", ReplaceWith("rgba(r, g, b, a)")) |
||||
data class RGBA(val r: Number, val g: Number, val b: Number, val a: Number) : CSSColorValue { |
||||
override fun toString(): String = "rgba($r, $g, $b, $a)" |
||||
} |
||||
|
||||
@Deprecated("use org.jetbrains.compose.web.css.hsl", ReplaceWith("hsl(h, s, l)")) |
||||
data class HSL(val h: CSSAngleValue, val s: Number, val l: Number) : CSSColorValue { |
||||
constructor(h: Number, s: Number, l: Number) : this(h.deg, s, l) |
||||
|
||||
override fun toString(): String = "hsl($h, $s%, $l%)" |
||||
} |
||||
|
||||
@Deprecated("use org.jetbrains.compose.web.css.hsla", ReplaceWith("hsla(h, s, l, a)")) |
||||
data class HSLA(val h: CSSAngleValue, val s: Number, val l: Number, val a: Number) : CSSColorValue { |
||||
constructor(h: Number, s: Number, l: Number, a: Number) : this(h.deg, s, l, a) |
||||
|
||||
override fun toString(): String = "hsla($h, $s%, $l%, $a)" |
||||
} |
||||
|
||||
inline val aliceblue get() = Color("aliceblue") |
||||
inline val antiquewhite get() = Color("antiquewhite") |
||||
inline val aquamarine get() = Color("aquamarine") |
||||
inline val azure get() = Color("azure") |
||||
inline val beige get() = Color("beige") |
||||
inline val bisque get() = Color("bisque") |
||||
inline val black get() = Color("black") |
||||
inline val blanchedalmond get() = Color("blanchedalmond") |
||||
inline val blue get() = Color("blue") |
||||
inline val blueviolet get() = Color("blueviolet") |
||||
inline val brown get() = Color("brown") |
||||
inline val burlywood get() = Color("burlywood") |
||||
inline val cadetblue get() = Color("cadetblue") |
||||
inline val chartreuse get() = Color("chartreuse") |
||||
inline val chocolate get() = Color("chocolate") |
||||
inline val cornflowerblue get() = Color("cornflowerblue") |
||||
inline val cornsilk get() = Color("cornsilk") |
||||
inline val crimson get() = Color("crimson") |
||||
inline val cyan get() = Color("cyan") |
||||
inline val darkblue get() = Color("darkblue") |
||||
inline val darkcyan get() = Color("darkcyan") |
||||
inline val darkgoldenrod get() = Color("darkgoldenrod") |
||||
inline val darkgray get() = Color("darkgray") |
||||
inline val darkgreen get() = Color("darkgreen") |
||||
inline val darkkhaki get() = Color("darkkhaki") |
||||
inline val darkmagenta get() = Color("darkmagenta") |
||||
inline val darkolivegreen get() = Color("darkolivegreen") |
||||
inline val darkorange get() = Color("darkorange") |
||||
inline val darkorchid get() = Color("darkorchid") |
||||
inline val darkred get() = Color("darkred") |
||||
inline val darksalmon get() = Color("darksalmon") |
||||
inline val darkslateblue get() = Color("darkslateblue") |
||||
inline val darkslategray get() = Color("darkslategray") |
||||
inline val darkturquoise get() = Color("darkturquoise") |
||||
inline val darkviolet get() = Color("darkviolet") |
||||
inline val deeppink get() = Color("deeppink") |
||||
inline val deepskyblue get() = Color("deepskyblue") |
||||
inline val dimgray get() = Color("dimgray") |
||||
inline val dodgerblue get() = Color("dodgerblue") |
||||
inline val firebrick get() = Color("firebrick") |
||||
inline val floralwhite get() = Color("floralwhite") |
||||
inline val forestgreen get() = Color("forestgreen") |
||||
inline val fuchsia get() = Color("fuchsia") |
||||
inline val gainsboro get() = Color("gainsboro") |
||||
inline val ghostwhite get() = Color("ghostwhite") |
||||
inline val goldenrod get() = Color("goldenrod") |
||||
inline val gold get() = Color("gold") |
||||
inline val gray get() = Color("gray") |
||||
inline val green get() = Color("green") |
||||
inline val greenyellow get() = Color("greenyellow") |
||||
inline val honeydew get() = Color("honeydew") |
||||
inline val hotpink get() = Color("hotpink") |
||||
inline val indianred get() = Color("indianred") |
||||
inline val indigo get() = Color("indigo") |
||||
inline val ivory get() = Color("ivory") |
||||
inline val khaki get() = Color("khaki") |
||||
inline val lavenderblush get() = Color("lavenderblush") |
||||
inline val lavender get() = Color("lavender") |
||||
inline val lawngreen get() = Color("lawngreen") |
||||
inline val lemonchiffon get() = Color("lemonchiffon") |
||||
inline val lightblue get() = Color("lightblue") |
||||
inline val lightcoral get() = Color("lightcoral") |
||||
inline val lightcyan get() = Color("lightcyan") |
||||
inline val lightgoldenrodyellow get() = Color("lightgoldenrodyellow") |
||||
inline val lightgray get() = Color("lightgray") |
||||
inline val lightgreen get() = Color("lightgreen") |
||||
inline val lightpink get() = Color("lightpink") |
||||
inline val lightsalmon get() = Color("lightsalmon") |
||||
inline val lightseagreen get() = Color("lightseagreen") |
||||
inline val lightskyblue get() = Color("lightskyblue") |
||||
inline val lightslategray get() = Color("lightslategray") |
||||
inline val lightsteelblue get() = Color("lightsteelblue") |
||||
inline val lightyellow get() = Color("lightyellow") |
||||
inline val limegreen get() = Color("limegreen") |
||||
inline val lime get() = Color("lime") |
||||
inline val linen get() = Color("linen") |
||||
inline val magenta get() = Color("magenta") |
||||
inline val maroon get() = Color("maroon") |
||||
inline val mediumaquamarine get() = Color("mediumaquamarine") |
||||
inline val mediumblue get() = Color("mediumblue") |
||||
inline val mediumorchid get() = Color("mediumorchid") |
||||
inline val mediumpurple get() = Color("mediumpurple") |
||||
inline val mediumseagreen get() = Color("mediumseagreen") |
||||
inline val mediumslateblue get() = Color("mediumslateblue") |
||||
inline val mediumspringgreen get() = Color("mediumspringgreen") |
||||
inline val mediumturquoise get() = Color("mediumturquoise") |
||||
inline val mediumvioletred get() = Color("mediumvioletred") |
||||
inline val midnightblue get() = Color("midnightblue") |
||||
inline val mintcream get() = Color("mintcream") |
||||
inline val mistyrose get() = Color("mistyrose") |
||||
inline val moccasin get() = Color("moccasin") |
||||
inline val navajowhite get() = Color("navajowhite") |
||||
inline val navi get() = Color("navi") |
||||
inline val oldlace get() = Color("oldlace") |
||||
inline val olivedrab get() = Color("olivedrab") |
||||
inline val olive get() = Color("olive") |
||||
inline val orange get() = Color("orange") |
||||
inline val orangered get() = Color("orangered") |
||||
inline val orchid get() = Color("orchid") |
||||
inline val palegoldenrod get() = Color("palegoldenrod") |
||||
inline val palegreen get() = Color("palegreen") |
||||
inline val paleturquoise get() = Color("paleturquoise") |
||||
inline val palevioletred get() = Color("palevioletred") |
||||
inline val papayawhip get() = Color("papayawhip") |
||||
inline val peachpuff get() = Color("peachpuff") |
||||
inline val peru get() = Color("peru") |
||||
inline val pink get() = Color("pink") |
||||
inline val plum get() = Color("plum") |
||||
inline val powderblue get() = Color("powderblue") |
||||
inline val purple get() = Color("purple") |
||||
inline val rebeccapurple get() = Color("rebeccapurple") |
||||
inline val red get() = Color("red") |
||||
inline val rosybrown get() = Color("rosybrown") |
||||
inline val royalblue get() = Color("royalblue") |
||||
inline val saddlebrown get() = Color("saddlebrown") |
||||
inline val salmon get() = Color("salmon") |
||||
inline val sandybrown get() = Color("sandybrown") |
||||
inline val seagreen get() = Color("seagreen") |
||||
inline val seashell get() = Color("seashell") |
||||
inline val sienna get() = Color("sienna") |
||||
inline val silver get() = Color("silver") |
||||
inline val skyblue get() = Color("skyblue") |
||||
inline val slateblue get() = Color("slateblue") |
||||
inline val slategray get() = Color("slategray") |
||||
inline val snow get() = Color("snow") |
||||
inline val springgreen get() = Color("springgreen") |
||||
inline val steelblue get() = Color("steelblue") |
||||
inline val teal get() = Color("teal") |
||||
inline val thistle get() = Color("thistle") |
||||
inline val tomato get() = Color("tomato") |
||||
inline val turquoise get() = Color("turquoise") |
||||
inline val violet get() = Color("violet") |
||||
inline val wheat get() = Color("wheat") |
||||
inline val white get() = Color("white") |
||||
inline val whitesmoke get() = Color("whitesmoke") |
||||
inline val yellowgreen get() = Color("yellowgreen") |
||||
inline val yellow get() = Color("yellow") |
||||
|
||||
inline val transparent get() = Color("transparent") |
||||
inline val currentColor get() = Color("currentColor") |
||||
} |
||||
|
||||
fun Color(name: String): CSSColorValue = name.unsafeCast<CSSColorValue>() |
||||
|
||||
private class RGB(val r: Number, val g: Number, val b: Number): CSSColorValue { |
||||
override fun toString(): String = "rgb($r, $g, $b)" |
||||
} |
||||
|
||||
private class RGBA(val r: Number, val g: Number, val b: Number, val a: Number) : CSSColorValue { |
||||
override fun toString(): String = "rgba($r, $g, $b, $a)" |
||||
} |
||||
|
||||
private class HSL(val h: CSSAngleValue, val s: Number, val l: Number) : CSSColorValue { |
||||
override fun toString(): String = "hsl($h, $s%, $l%)" |
||||
} |
||||
|
||||
private class HSLA(val h: CSSAngleValue, val s: Number, val l: Number, val a: Number) : CSSColorValue { |
||||
override fun toString(): String = "hsla($h, $s%, $l%, $a)" |
||||
} |
||||
|
||||
fun rgb(r: Number, g: Number, b: Number): CSSColorValue = RGB(r, g, b) |
||||
fun rgba(r: Number, g: Number, b: Number, a: Number): CSSColorValue = RGBA(r, g, b, a) |
||||
fun hsl(h: CSSAngleValue, s: Number, l: Number): CSSColorValue = HSL(h, s, l) |
||||
fun hsl(h: Number, s: Number, l: Number): CSSColorValue = HSL(h.deg, s, l) |
||||
fun hsla(h: CSSAngleValue, s: Number, l: Number, a: Number): CSSColorValue = HSLA(h, s, l, a) |
||||
fun hsla(h: Number, s: Number, l: Number, a: Number): CSSColorValue = HSLA(h.deg, s, l, a) |
@ -0,0 +1,23 @@
|
||||
/* |
||||
* 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. |
||||
*/ |
||||
|
||||
@file:Suppress("UNUSED", "NOTHING_TO_INLINE", "FunctionName") |
||||
package org.jetbrains.compose.web.css |
||||
|
||||
import org.jetbrains.compose.web.* |
||||
|
||||
expect interface StylePropertyValue |
||||
|
||||
expect interface StylePropertyNumber: StylePropertyValue |
||||
expect interface StylePropertyString: StylePropertyValue |
||||
|
||||
inline fun StylePropertyValue(value: String): StylePropertyString = value.unsafeCast<StylePropertyString>() |
||||
inline fun StylePropertyValue(value: Number): StylePropertyNumber = value.unsafeCast<StylePropertyNumber>() |
||||
|
||||
expect interface CSSStyleValue: StylePropertyValue { |
||||
actual override fun toString(): String |
||||
} |
||||
|
||||
inline fun CSSStyleValue(value: String): CSSStyleValue = StylePropertyValue(value).unsafeCast<CSSStyleValue>() |
@ -0,0 +1,196 @@
|
||||
/* |
||||
* 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. |
||||
*/ |
||||
|
||||
@file:Suppress("NOTHING_TO_INLINE", "unused") |
||||
|
||||
package org.jetbrains.compose.web.css |
||||
|
||||
import org.jetbrains.compose.web.attributes.HtmlAttrMarker |
||||
import org.jetbrains.compose.web.internal.runtime.ComposeWebInternalApi |
||||
import kotlin.properties.ReadOnlyProperty |
||||
import org.jetbrains.compose.web.* |
||||
|
||||
@Deprecated( |
||||
message = "Renamed to StyleScope", |
||||
replaceWith = ReplaceWith("StyleScope", "org.jetbrains.compose.web.css.StyleScope") |
||||
) |
||||
typealias StyleBuilder = StyleScope |
||||
|
||||
/** |
||||
* StyleScope serves for two main purposes. Passed as a builder context (in [AttrsScope]), it |
||||
* makes it possible to: |
||||
* 1. Add inlined css properties to the element (@see [property]) |
||||
* 2. Set values to CSS variables (@see [variable]) |
||||
*/ |
||||
@HtmlAttrMarker |
||||
interface StyleScope { |
||||
/** |
||||
* Adds arbitrary CSS property to the inline style of the element |
||||
* @param propertyName - the name of css property as [per spec](https://developer.mozilla.org/en-US/docs/Web/CSS/Reference) |
||||
* @param value - the value, it can be either String or specialized type like [CSSNumeric] or [CSSColorValue] |
||||
* |
||||
* Most frequent CSS property values can be set via specialized methods, like [width], [display] etc. |
||||
* |
||||
* Example: |
||||
* ``` |
||||
* Div({ |
||||
* style { |
||||
* property("some-exotic-css-property", "I am a string value") |
||||
* property("some-exotic-css-property-width", 5.px) |
||||
* } |
||||
* }) |
||||
* ``` |
||||
*/ |
||||
fun property(propertyName: String, value: StylePropertyValue) |
||||
fun variable(variableName: String, value: StylePropertyValue) |
||||
|
||||
fun property(propertyName: String, value: String) = property(propertyName, StylePropertyValue(value)) |
||||
fun property(propertyName: String, value: Number) = property(propertyName, StylePropertyValue(value)) |
||||
fun variable(variableName: String, value: String) = variable(variableName, StylePropertyValue(value)) |
||||
fun variable(variableName: String, value: Number) = variable(variableName, StylePropertyValue(value)) |
||||
|
||||
operator fun <TValue : StylePropertyValue> CSSStyleVariable<TValue>.invoke(value: TValue) { |
||||
variable(name, value.toString()) |
||||
} |
||||
|
||||
operator fun CSSStyleVariable<StylePropertyString>.invoke(value: String) { |
||||
variable(name, value) |
||||
} |
||||
|
||||
operator fun CSSStyleVariable<StylePropertyNumber>.invoke(value: Number) { |
||||
variable(name, value) |
||||
} |
||||
} |
||||
|
||||
internal inline fun variableValue(variableName: String, fallback: StylePropertyValue? = null) = |
||||
"var(--$variableName${fallback?.let { ", $it" } ?: ""})" |
||||
|
||||
expect interface CSSVariableValueAs<out T : StylePropertyValue> |
||||
|
||||
inline fun <TValue> CSSVariableValue(value: StylePropertyValue) = |
||||
value.unsafeCast<TValue>() |
||||
|
||||
inline fun <TValue> CSSVariableValue(value: String) = |
||||
CSSVariableValue<TValue>(StylePropertyValue(value)) |
||||
|
||||
// after adding `variable` word `add` became ambiguous |
||||
@Deprecated( |
||||
"use property instead, will remove it soon", |
||||
ReplaceWith("property(propertyName, value)") |
||||
) |
||||
fun StyleScope.add( |
||||
propertyName: String, |
||||
value: StylePropertyValue |
||||
) = property(propertyName, value) |
||||
|
||||
interface CSSVariable { |
||||
val name: String |
||||
} |
||||
|
||||
class CSSStyleVariable<out TValue : StylePropertyValue>(override val name: String) : CSSVariable |
||||
|
||||
fun <TValue : StylePropertyValue> CSSStyleVariable<TValue>.value(fallback: TValue? = null) = |
||||
CSSVariableValue<TValue>( |
||||
variableValue( |
||||
name, |
||||
fallback |
||||
) |
||||
) |
||||
|
||||
fun <TValue> CSSStyleVariable<TValue>.value(fallback: TValue? = null) |
||||
where TValue : CSSVariableValueAs<TValue>, |
||||
TValue : StylePropertyValue = |
||||
CSSVariableValue<TValue>( |
||||
variableValue( |
||||
name, |
||||
fallback |
||||
) |
||||
) |
||||
|
||||
/** |
||||
* Introduces CSS variable that can be later referred anywhere in [StyleSheet] |
||||
* |
||||
* Example: |
||||
* ``` |
||||
* object AppCSSVariables { |
||||
* val width by variable<CSSUnitValue>() |
||||
* val stringHeight by variable<StylePropertyString>() |
||||
* val order by variable<StylePropertyNumber>() |
||||
* } |
||||
* |
||||
* object AppStylesheet : StyleSheet() { |
||||
* val classWithProperties by style { |
||||
* AppCSSVariables.width(100.px) |
||||
* property("width", AppCSSVariables.width.value()) |
||||
* } |
||||
*``` |
||||
* |
||||
*/ |
||||
fun <TValue : StylePropertyValue> variable() = |
||||
ReadOnlyProperty<Any?, CSSStyleVariable<TValue>> { _, property -> |
||||
CSSStyleVariable(property.name) |
||||
} |
||||
|
||||
interface StyleHolder { |
||||
@ComposeWebInternalApi |
||||
val properties: StylePropertyList |
||||
@ComposeWebInternalApi |
||||
val variables: StylePropertyList |
||||
} |
||||
|
||||
@Deprecated( |
||||
message = "Renamed to StyleScopeBuilder", |
||||
replaceWith = ReplaceWith("StyleScopeBuilder", "org.jetbrains.compose.web.css.StyleScopeBuilder") |
||||
) |
||||
typealias StyleBuilderImpl = StyleScopeBuilder |
||||
|
||||
@Suppress("EqualsOrHashCode") |
||||
open class StyleScopeBuilder : StyleScope, StyleHolder { |
||||
override val properties: MutableStylePropertyList = mutableListOf() |
||||
override val variables: MutableStylePropertyList = mutableListOf() |
||||
|
||||
override fun property(propertyName: String, value: StylePropertyValue) { |
||||
properties.add(StylePropertyDeclaration(propertyName, value)) |
||||
} |
||||
|
||||
override fun variable(variableName: String, value: StylePropertyValue) { |
||||
variables.add(StylePropertyDeclaration(variableName, value)) |
||||
} |
||||
|
||||
// StylePropertyValue is js native object without equals |
||||
override fun equals(other: Any?): Boolean { |
||||
return if (other is StyleHolder) { |
||||
properties.nativeEquals(other.properties) && |
||||
variables.nativeEquals(other.variables) |
||||
} else false |
||||
} |
||||
|
||||
@ComposeWebInternalApi |
||||
internal fun copyFrom(sb: StyleHolder) { |
||||
properties.addAll(sb.properties) |
||||
variables.addAll(sb.variables) |
||||
} |
||||
} |
||||
|
||||
data class StylePropertyDeclaration( |
||||
val name: String, |
||||
val value: StylePropertyValue |
||||
) { |
||||
constructor(name: String, value: String) : this(name, value.unsafeCast<StylePropertyValue>()) |
||||
constructor(name: String, value: Number) : this(name, value.unsafeCast<StylePropertyValue>()) |
||||
} |
||||
typealias StylePropertyList = List<StylePropertyDeclaration> |
||||
typealias MutableStylePropertyList = MutableList<StylePropertyDeclaration> |
||||
|
||||
internal fun StylePropertyList.nativeEquals(properties: StylePropertyList): Boolean { |
||||
if (this.size != properties.size) return false |
||||
|
||||
var index = 0 |
||||
return all { prop -> |
||||
val otherProp = properties[index++] |
||||
prop.name == otherProp.name && |
||||
prop.value.toString() == otherProp.value.toString() |
||||
} |
||||
} |
@ -0,0 +1,15 @@
|
||||
/* |
||||
* 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.keywords |
||||
|
||||
import org.jetbrains.compose.web.css.CSSKeywordValue |
||||
import org.jetbrains.compose.web.* |
||||
|
||||
expect interface CSSAutoKeyword : CSSKeywordValue |
||||
|
||||
inline val auto: CSSAutoKeyword |
||||
get() = CSSKeywordValue("auto").unsafeCast<CSSAutoKeyword>() |
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue