Browse Source

Remove CSS Typed OM API (#786)

pull/798/head
Abasov Akif 3 years ago committed by GitHub
parent
commit
0a90ae2194
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 3
      web/benchmark-core/src/jsMain/kotlin/com/sample/components/Layout.kt
  2. 1
      web/benchmark-core/src/jsMain/kotlin/com/sample/content/CodeSamplesSwitcher.kt
  3. 4
      web/benchmark-core/src/jsMain/kotlin/com/sample/content/CodeSnippets.kt
  4. 2
      web/benchmark-core/src/jsMain/kotlin/com/sample/content/Footer.kt
  5. 2
      web/benchmark-core/src/jsMain/kotlin/com/sample/content/Header.kt
  6. 2
      web/benchmark-core/src/jsMain/kotlin/com/sample/style/Stylesheet.kt
  7. 1
      web/core/build.gradle.kts
  8. 3
      web/core/src/jsMain/kotlin/androidx/compose/web/DomApplier.kt
  9. 38
      web/core/src/jsMain/kotlin/androidx/compose/web/css/BrowserAPI.kt
  10. 299
      web/core/src/jsMain/kotlin/androidx/compose/web/css/CSS.kt
  11. 183
      web/core/src/jsMain/kotlin/androidx/compose/web/css/CSSEnums.kt
  12. 15
      web/core/src/jsMain/kotlin/androidx/compose/web/css/CSSHelpers.kt
  13. 12
      web/core/src/jsMain/kotlin/androidx/compose/web/css/CSSKeywords.kt
  14. 6
      web/core/src/jsMain/kotlin/androidx/compose/web/css/CSSMediaRule.kt
  15. 14
      web/core/src/jsMain/kotlin/androidx/compose/web/css/CSSOperations.kt
  16. 15
      web/core/src/jsMain/kotlin/androidx/compose/web/css/CSSPolyfill.kt
  17. 219
      web/core/src/jsMain/kotlin/androidx/compose/web/css/CSSProperties.kt
  18. 259
      web/core/src/jsMain/kotlin/androidx/compose/web/css/CSSUnits.kt
  19. 15
      web/core/src/jsMain/kotlin/androidx/compose/web/css/Color.kt
  20. 87
      web/core/src/jsMain/kotlin/androidx/compose/web/css/StyleBuilder.kt
  21. 27
      web/core/src/jsMain/kotlin/androidx/compose/web/css/StylePropertyValue.kt
  22. 14
      web/core/src/jsMain/kotlin/androidx/compose/web/css/keywords/Keywords.kt
  23. 2
      web/core/src/jsMain/kotlin/androidx/compose/web/css/selectors/CSSSelectors.kt
  24. 8
      web/core/src/jsMain/kotlin/androidx/compose/web/elements/Style.kt
  25. 116
      web/core/src/jsTest/kotlin/CSSEnums.kt
  26. 4
      web/core/src/jsTest/kotlin/CSSStylesheetTests.kt
  27. 48
      web/core/src/jsTest/kotlin/CSSUnitApiTests.kt
  28. 1
      web/core/src/jsTest/kotlin/InlineStyleTests.kt
  29. 27
      web/core/src/jsTest/kotlin/StaticComposableTests.kt
  30. 24
      web/integration-core/src/jsMain/kotlin/androidx/compose/web/sample/Sample.kt
  31. 1
      web/widgets/src/jsMain/kotlin/Modifier.kt

3
web/benchmark-core/src/jsMain/kotlin/com/sample/components/Layout.kt

@ -2,10 +2,7 @@ package com.sample.components
import androidx.compose.runtime.Composable
import org.jetbrains.compose.web.css.*
import org.jetbrains.compose.web.css.selectors.*
import org.jetbrains.compose.web.attributes.*
import org.jetbrains.compose.web.dom.*
import org.jetbrains.compose.web.*
import com.sample.style.WtContainer
import com.sample.style.WtOffsets
import com.sample.style.WtSections

1
web/benchmark-core/src/jsMain/kotlin/com/sample/content/CodeSamplesSwitcher.kt

@ -5,7 +5,6 @@ import org.jetbrains.compose.web.css.*
import org.jetbrains.compose.web.css.selectors.*
import org.jetbrains.compose.web.attributes.*
import org.jetbrains.compose.web.dom.*
import org.jetbrains.compose.web.*
import com.sample.style.AppStylesheet
private object SwitcherVariables : CSSVariables {

4
web/benchmark-core/src/jsMain/kotlin/com/sample/content/CodeSnippets.kt

@ -5,13 +5,11 @@ import androidx.compose.runtime.getValue
import androidx.compose.runtime.setValue
import androidx.compose.runtime.mutableStateOf
import org.jetbrains.compose.web.css.*
import org.jetbrains.compose.web.css.selectors.*
import org.jetbrains.compose.web.attributes.*
import org.jetbrains.compose.web.dom.*
import org.jetbrains.compose.web.*
import com.sample.HighlightJs
import com.sample.components.ContainerInSection
import com.sample.style.*
import org.jetbrains.compose.web.css.keywords.auto
import org.w3c.dom.HTMLElement
private fun HTMLElement.setHighlightedCode(code: String) {

2
web/benchmark-core/src/jsMain/kotlin/com/sample/content/Footer.kt

@ -2,10 +2,8 @@ package com.sample.content
import androidx.compose.runtime.Composable
import org.jetbrains.compose.web.css.*
import org.jetbrains.compose.web.css.selectors.*
import org.jetbrains.compose.web.attributes.*
import org.jetbrains.compose.web.dom.*
import org.jetbrains.compose.web.*
import com.sample.style.*

2
web/benchmark-core/src/jsMain/kotlin/com/sample/content/Header.kt

@ -2,10 +2,8 @@ package com.sample.content
import androidx.compose.runtime.Composable
import org.jetbrains.compose.web.css.*
import org.jetbrains.compose.web.css.selectors.*
import org.jetbrains.compose.web.attributes.*
import org.jetbrains.compose.web.dom.*
import org.jetbrains.compose.web.*
import com.sample.style.*
import kotlinx.browser.window

2
web/benchmark-core/src/jsMain/kotlin/com/sample/style/Stylesheet.kt

@ -20,7 +20,7 @@ object AppCSSVariables : CSSVariables {
val wtH3FontSize by variable<CSSUnitValue>()
val wtH3LineHeight by variable<CSSUnitValue>()
val wtColCount by variable<Int>()
val wtColCount by variable<StylePropertyNumber>()
}

1
web/core/build.gradle.kts

@ -31,7 +31,6 @@ kotlin {
val jsMain by getting {
dependencies {
implementation(kotlin("stdlib-js"))
implementation(npm("css-typed-om", "0.4.0"))
}
}

3
web/core/src/jsMain/kotlin/androidx/compose/web/DomApplier.kt

@ -3,7 +3,6 @@ package org.jetbrains.compose.web
import androidx.compose.runtime.AbstractApplier
import org.jetbrains.compose.web.attributes.WrappedEventListener
import org.jetbrains.compose.web.css.StyleHolder
import org.jetbrains.compose.web.css.attributeStyleMap
import org.jetbrains.compose.web.dom.setProperty
import org.jetbrains.compose.web.dom.setVariable
import kotlinx.browser.document
@ -109,7 +108,7 @@ class DomElementWrapper(override val node: HTMLElement): DomNodeWrapper(node) {
node.removeAttribute("style")
style?.properties?.forEach { (name, value) ->
setProperty(node.attributeStyleMap, name, value)
setProperty(node.style, name, value)
}
style?.variables?.forEach { (name, value) ->
setVariable(node.style, name, value)

38
web/core/src/jsMain/kotlin/androidx/compose/web/css/BrowserAPI.kt

@ -0,0 +1,38 @@
/*
* 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.w3c.dom.css.*
import org.w3c.dom.css.StyleSheet
inline val StyleSheet.cssRules
get() = this.asDynamic().cssRules.unsafeCast<CSSRuleList>()
inline fun StyleSheet.deleteRule(index: Int) {
this.asDynamic().deleteRule(index)
}
fun StyleSheet.insertRule(cssRule: String, index: Int? = null): Int {
return if (index != null) {
this.asDynamic().insertRule(cssRule, index).unsafeCast<Int>()
} else {
this.asDynamic().insertRule(cssRule).unsafeCast<Int>()
}
}
inline operator fun CSSRuleList.get(index: Int): CSSRule {
return this.asDynamic()[index].unsafeCast<CSSRule>()
}
@Suppress("NOTHING_TO_INLINE")
inline fun <T : Any> jsObject(): T =
js("({})")
inline fun <T : Any> jsObject(builder: T.() -> Unit): T =
jsObject<T>().apply(builder)

299
web/core/src/jsMain/kotlin/androidx/compose/web/css/CSS.kt

@ -1,299 +0,0 @@
@file:Suppress("UNUSED", "NOTHING_TO_INLINE")
package org.jetbrains.compose.web.css
import kotlinx.browser.window
import org.w3c.dom.DOMMatrix
import org.w3c.dom.DOMMatrixReadOnly
import org.w3c.dom.Element
import org.w3c.dom.css.CSSRule
import org.w3c.dom.css.CSSRuleList
import org.w3c.dom.css.CSSStyleRule
import org.w3c.dom.css.ElementCSSInlineStyle
import org.w3c.dom.css.StyleSheet
inline val StyleSheet.cssRules
get() = this.asDynamic().cssRules.unsafeCast<CSSRuleList>()
inline fun StyleSheet.deleteRule(index: Int) {
this.asDynamic().deleteRule(index)
}
inline val CSSStyleRule.styleMap
get() = this.asDynamic().styleMap.unsafeCast<StylePropertyMap>()
inline operator fun CSSRuleList.get(index: Int): CSSRule {
return this.asDynamic()[index].unsafeCast<CSSRule>()
}
fun StyleSheet.insertRule(cssRule: String, index: Int? = null): Int {
return if (index != null) {
this.asDynamic().insertRule(cssRule, index).unsafeCast<Int>()
} else {
this.asDynamic().insertRule(cssRule).unsafeCast<Int>()
}
}
val ElementCSSInlineStyle.attributeStyleMap
get() = this.asDynamic().attributeStyleMap.unsafeCast<StylePropertyMap>()
external interface CSSStyleValue : StylePropertyValue
@JsName("CSSStyleValue")
open external class CSSStyleValueJS : CSSStyleValue {
companion object {
fun parse(property: String, cssText: String): CSSStyleValue
fun parseAll(property: String, cssText: String): Array<CSSStyleValue>
}
}
external class CSSVariableReferenceValue(
variable: String,
fallback: CSSUnparsedValue? = definedExternally
) {
val variable: String
val fallback: CSSUnparsedValue?
}
// type CSSUnparsedSegment = String | CSSVariableReferenceValue
interface CSSUnparsedSegment {
companion object {
operator fun invoke(value: String) = value.unsafeCast<CSSUnparsedSegment>()
operator fun invoke(value: CSSVariableReferenceValue) =
value.unsafeCast<CSSUnparsedSegment>()
}
}
fun CSSUnparsedSegment.asString() = this.asDynamic() as? String
fun CSSUnparsedSegment.asCSSVariableReferenceValue() =
this.asDynamic() as? CSSVariableReferenceValue
external class CSSUnparsedValue(members: Array<CSSUnparsedSegment>) : CSSStyleValue {
// TODO: [Symbol.iterator]() : IterableIterator<CSSUnparsedSegment>
fun forEach(handler: (CSSUnparsedSegment) -> Unit)
val length: Int
// readonly [index: number]: CSSUnparsedSegment
operator fun get(index: Int): CSSUnparsedSegment
operator fun set(index: Int, value: CSSUnparsedSegment)
}
// type CSSNumberish = number | CSSNumericValue
interface CSSNumberish {
companion object {
operator fun invoke(value: Number) = value.unsafeCast<CSSNumberish>()
operator fun invoke(value: CSSNumericValue) =
value.unsafeCast<CSSNumberish>()
}
}
fun CSSNumberish.asNumber() = this.asDynamic() as? Number
fun CSSNumberish.asCSSNumericValue(): CSSNumericValue? = this.asDynamic() as? CSSNumericValue
// declare enum CSSNumericBaseType {
// 'length',
// 'angle',
// 'time',
// 'frequency',
// 'resolution',
// 'flex',
// 'percent',
// }
enum class CSSNumericBaseType(val value: String) {
@JsName("_length")
length("length"),
angle("angle"),
time("time"),
frequency("frequency"),
resolution("resolution"),
flex("flex"),
percent("percent")
}
external interface CSSNumericType {
val length: Number
val angle: Number
val time: Number
val frequency: Number
val resolution: Number
val flex: Number
val percent: Number
// percentHint: CSSNumericBaseType
}
val CSSNumericType.percentHint
get() = CSSNumericBaseType.valueOf(this.asDynamic().percentHint)
// set(value) { this.asDynamic().percentHint = value.value }
external interface CSSNumericValue : CSSStyleValue
// declare enum CSSMathOperator {
// 'sum',
// 'product',
// 'negate',
// 'invert',
// 'min',
// 'max',
// 'clamp',
// }
enum class CSSMathOperator(val value: String) {
sum("sum"),
product("product"),
negate("negate"),
invert("invert"),
min("min"),
max("max"),
clamp("clamp")
}
open external class CSSMathValue : CSSNumericValue
val CSSMathValue.operator
get() = CSSMathOperator.valueOf(this.asDynamic().operator)
// set(value) { this.asDynamic().operator = value.value }
external class CSSMathSum(vararg args: CSSNumberish) : CSSMathValue {
val values: CSSNumericArray
}
external class CSSMathProduct(vararg args: CSSNumberish) : CSSMathValue {
val values: CSSNumericArray
}
external class CSSMathNegate(arg: CSSNumberish) : CSSMathValue {
val value: CSSNumericValue
}
external class CSSMathInvert(arg: CSSNumberish) : CSSMathValue {
val value: CSSNumericValue
}
external class CSSMathMin(vararg args: CSSNumberish) : CSSMathValue {
val values: CSSNumericArray
}
external class CSSMathMax(vararg args: CSSNumberish) : CSSMathValue {
val values: CSSNumericArray
}
external class CSSNumericArray {
// TODO: [Symbol.iterator]() : IterableIterator<CSSNumericValue>
fun forEach(handler: (CSSNumericValue) -> Unit)
val length: Int
// readonly [index: number]: CSSNumericValue
operator fun get(index: Int): CSSNumericValue
}
external class CSSTransformValue(transforms: Array<CSSTransformComponent>) : CSSStyleValue {
// [Symbol.iterator]() : IterableIterator<CSSTransformComponent>
fun forEach(handler: (CSSTransformComponent) -> Unit)
val length: Int
// [index: number]: CSSTransformComponent
operator fun get(index: Int): CSSTransformComponent
operator fun set(index: Int, value: CSSTransformComponent)
val is2D: Boolean
fun toMatrix(): DOMMatrix
}
open external class CSSTransformComponent {
val is2D: Boolean
fun toMatrix(): DOMMatrix
// toString() : string
}
external class CSSTranslate(
x: CSSNumericValue,
y: CSSNumericValue,
z: CSSNumericValue? = definedExternally
) : CSSTransformComponent {
val x: CSSNumericValue
val y: CSSNumericValue
val z: CSSNumericValue
}
external class CSSRotate(angle: CSSNumericValue) : CSSTransformComponent {
constructor(x: CSSNumberish, y: CSSNumberish, z: CSSNumberish, angle: CSSNumericValue)
val x: CSSNumberish
val y: CSSNumberish
val z: CSSNumberish
val angle: CSSNumericValue
}
external class CSSScale(
x: CSSNumberish,
y: CSSNumberish,
z: CSSNumberish? = definedExternally
) : CSSTransformComponent {
val x: CSSNumberish
val y: CSSNumberish
val z: CSSNumberish
}
external class CSSSkew(ax: CSSNumericValue, ay: CSSNumericValue) : CSSTransformComponent {
val ax: CSSNumericValue
val ay: CSSNumericValue
}
external class CSSSkewX(ax: CSSNumericValue) : CSSTransformComponent {
val ax: CSSNumericValue
}
external class CSSSkewY(ay: CSSNumericValue) : CSSTransformComponent {
val ay: CSSNumericValue
}
/* Note that skew(x,y) is *not* the same as skewX(x) skewY(y),
thus the separate interfaces for all three. */
external class CSSPerspective(length: CSSNumericValue) : CSSTransformComponent {
val length: CSSNumericValue
}
external class CSSMatrixComponent(
matrix: DOMMatrixReadOnly,
options: CSSMatrixComponentOptions? = definedExternally
) : CSSTransformComponent {
val matrix: DOMMatrix
}
external interface CSSMatrixComponentOptions {
val is2D: Boolean
}
external class CSSImageValue : CSSStyleValue
open external class StylePropertyMapReadOnly {
// TODO: [Symbol.iterator]() : IterableIterator<[string, CSSStyleValue[]]>
fun get(property: String): CSSStyleValue? // CSSStyleValue | undefined
fun getAll(property: String): Array<CSSStyleValue>
fun has(property: String): Boolean
val size: Number
}
fun StylePropertyMapReadOnly.forEach(handler: (String, Array<CSSStyleValue>) -> Unit) {
this.asDynamic().forEach { entry: Array<dynamic> ->
handler(
entry[0].unsafeCast<String>(),
entry[1].unsafeCast<Array<CSSStyleValue>>()
)
}
}
// CSSStyleValue | string
external interface StylePropertyValue
external class StylePropertyMap : StylePropertyMapReadOnly {
fun set(property: String, vararg values: StylePropertyValue)
fun append(property: String, vararg values: StylePropertyValue)
fun delete(property: String)
fun clear()
}
inline fun Element.computedStyleMap(): StylePropertyMapReadOnly =
this.asDynamic().computedStyleMap().unsafeCast<StylePropertyMapReadOnly>()
@Suppress("unused")
val cssTypedOMPolyfill = CSSTypedOMPolyfill.default(window)

183
web/core/src/jsMain/kotlin/androidx/compose/web/css/CSSEnums.kt

@ -0,0 +1,183 @@
@file:Suppress("Unused", "NOTHING_TO_INLINE", "NESTED_CLASS_IN_EXTERNAL_INTERFACE", "INLINE_EXTERNAL_DECLARATION", "WRONG_BODY_OF_EXTERNAL_DECLARATION", "NESTED_EXTERNAL_DECLARATION")
package org.jetbrains.compose.web.css
external interface StylePropertyEnum: StylePropertyString
inline val StylePropertyEnum.name get() = this.unsafeCast<String>()
inline val StylePropertyEnum.value get() = this.unsafeCast<String>()
external interface LineStyle: StylePropertyEnum {
external companion object {
inline val None get() = LineStyle("none")
inline val Hidden get() = LineStyle("hidden")
inline val Dotted get() = LineStyle("dotted")
inline val Dashed get() = LineStyle("dashed")
inline val Solid get() = LineStyle("solid")
inline val Double get() = LineStyle("double")
inline val Groove get() = LineStyle("groove")
inline val Ridge get() = LineStyle("ridge")
inline val Inset get() = LineStyle("inset")
inline val Outset get() = LineStyle("outset")
}
}
inline fun LineStyle(value: String) = value.unsafeCast<LineStyle>()
external interface DisplayStyle: StylePropertyEnum {
external companion object {
inline val Block get() = DisplayStyle("block")
inline val Inline get() = DisplayStyle("inline")
inline val InlineBlock get() = DisplayStyle("inline-block")
inline val Flex get() = DisplayStyle("flex")
inline val LegacyInlineFlex get() = DisplayStyle("inline-flex")
inline val Grid get() = DisplayStyle("grid")
inline val LegacyInlineGrid get() = DisplayStyle("inline-grid")
inline val FlowRoot get() = DisplayStyle("flow-root")
inline val None get() = DisplayStyle("none")
inline val Contents get() = DisplayStyle("contents")
// TODO(shabunc): This properties behave them iconsistenly in both Chrome and Firefox so I turned the off so far
// BlockFlow("block flow")
// InlineFlow("inline flow")
// InlineFlowRoot("inline flow-root")
// BlocklFlex("block flex")
// InlineFlex("inline flex")
// BlockGrid("block grid")
// InlineGrid("inline grid")
// BlockFlowRoot("block flow-root")
inline val Table get() = DisplayStyle("table")
inline val TableRow get() = DisplayStyle("table-row")
inline val ListItem get() = DisplayStyle("list-item")
inline val Inherit get() = DisplayStyle("inherit")
inline val Initial get() = DisplayStyle("initial")
inline val Unset get() = DisplayStyle("unset")
}
}
inline fun DisplayStyle(value: String) = value.unsafeCast<DisplayStyle>()
external interface FlexDirection: StylePropertyEnum {
companion object {
inline val Row get() = FlexDirection("row")
inline val RowReverse get() = FlexDirection("row-reverse")
inline val Column get() = FlexDirection("column")
inline val ColumnReverse get() = FlexDirection("column-reverse")
}
}
inline fun FlexDirection(value: String) = value.unsafeCast<FlexDirection>()
external interface FlexWrap: StylePropertyEnum {
companion object {
inline val Wrap get() = FlexWrap("wrap")
inline val Nowrap get() = FlexWrap("nowrap")
inline val WrapReverse get() = FlexWrap("wrap-reverse")
}
}
inline fun FlexWrap(value: String) = value.unsafeCast<FlexWrap>()
external interface JustifyContent: StylePropertyEnum {
companion object {
inline val Center get() = JustifyContent("center")
inline val Start get() = JustifyContent("start")
inline val End get() = JustifyContent("end")
inline val FlexStart get() = JustifyContent("flex-start")
inline val FlexEnd get() = JustifyContent("flex-end")
inline val Left get() = JustifyContent("left")
inline val Right get() = JustifyContent("right")
inline val Normal get() = JustifyContent("normal")
inline val SpaceBetween get() = JustifyContent("space-between")
inline val SpaceAround get() = JustifyContent("space-around")
inline val SpaceEvenly get() = JustifyContent("space-evenly")
inline val Stretch get() = JustifyContent("stretch")
inline val Inherit get() = JustifyContent("inherit")
inline val Initial get() = JustifyContent("initial")
inline val Unset get() = JustifyContent("unset")
inline val SafeCenter get() = JustifyContent("safe center")
inline val UnsafeCenter get() = JustifyContent("unsafe center")
}
}
inline fun JustifyContent(value: String) = value.unsafeCast<JustifyContent>()
external interface AlignSelf: StylePropertyEnum {
companion object {
inline val Auto get() = AlignSelf("auto")
inline val Normal get() = AlignSelf("normal")
inline val Center get() = AlignSelf("center")
inline val Start get() = AlignSelf("start")
inline val End get() = AlignSelf("end")
inline val SelfStart get() = AlignSelf("self-start")
inline val SelfEnd get() = AlignSelf("self-end")
inline val FlexStart get() = AlignSelf("flex-start")
inline val FlexEnd get() = AlignSelf("flex-end")
inline val Baseline get() = AlignSelf("baseline")
// FirstBaseline("first baseline")
// LastBaseline("last baseline")
inline val Stretch get() = AlignSelf("stretch")
inline val SafeCenter get() = AlignSelf("safe center")
inline val UnsafeCenter get() = AlignSelf("unsafe center")
inline val Inherit get() = AlignSelf("inherit")
inline val Initial get() = AlignSelf("initial")
inline val Unset get() = AlignSelf("unset")
}
}
inline fun AlignSelf(value: String) = value.unsafeCast<AlignSelf>()
external interface AlignItems: StylePropertyEnum {
companion object {
inline val Normal get() = AlignItems("normal")
inline val Stretch get() = AlignItems("stretch")
inline val Center get() = AlignItems("center")
inline val Start get() = AlignItems("start")
inline val End get() = AlignItems("end")
inline val FlexStart get() = AlignItems("flex-start")
inline val FlexEnd get() = AlignItems("flex-end")
inline val Baseline get() = AlignItems("baseline")
// FirstBaseline("first baseline")
// LastBaseline("last baseline")
inline val SafeCenter get() = AlignItems("safe center")
inline val UnsafeCenter get() = AlignItems("unsafe center")
inline val Inherit get() = AlignItems("inherit")
inline val Initial get() = AlignItems("initial")
inline val Unset get() = AlignItems("unset")
}
}
inline fun AlignItems(value: String) = value.unsafeCast<AlignItems>()
external interface AlignContent: StylePropertyEnum {
companion object {
inline val Center get() = AlignContent("center")
inline val Start get() = AlignContent("start")
inline val End get() = AlignContent("end")
inline val FlexStart get() = AlignContent("flex-start")
inline val FlexEnd get() = AlignContent("flex-end")
inline val Baseline get() = AlignContent("baseline")
// FirstBaseline("first baseline")
// LastBaseline("last baseline")
inline val SafeCenter get() = AlignContent("safe center")
inline val UnsafeCenter get() = AlignContent("unsafe center")
inline val SpaceBetween get() = AlignContent("space-between")
inline val SpaceAround get() = AlignContent("space-around")
inline val SpaceEvenly get() = AlignContent("space-evenly")
inline val Stretch get() = AlignContent("stretch")
inline val Inherit get() = AlignContent("inherit")
inline val Initial get() = AlignContent("initial")
inline val Unset get() = AlignContent("unset")
}
}
inline fun AlignContent(value: String) = value.unsafeCast<AlignContent>()
external interface Position: StylePropertyEnum {
companion object {
inline val Static get() = Position("static")
inline val Relative get() = Position("relative")
inline val Absolute get() = Position("absolute")
inline val Sticky get() = Position("sticky")
inline val Fixed get() = Position("fixed")
}
}
inline fun Position(value: String) = value.unsafeCast<Position>()
typealias LanguageCode = String

15
web/core/src/jsMain/kotlin/androidx/compose/web/css/CSSHelpers.kt

@ -1,15 +0,0 @@
@file:Suppress("UNUSED")
package org.jetbrains.compose.web.css
interface CSSAutoValue : StylePropertyValue
val auto = "auto".unsafeCast<CSSAutoValue>()
enum class Direction {
rtl,
ltr;
override fun toString(): String = this.name
}
typealias LanguageCode = String

12
web/core/src/jsMain/kotlin/androidx/compose/web/css/CSSKeywords.kt

@ -0,0 +1,12 @@
/*
* 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
external interface CSSKeywordValue : CSSStyleValue
inline fun CSSKeywordValue(value: String): CSSKeywordValue = CSSStyleValue(value).unsafeCast<CSSKeywordValue>()

6
web/core/src/jsMain/kotlin/androidx/compose/web/css/CSSMediaRule.kt

@ -1,3 +1,5 @@
@file:Suppress("unused", "MemberVisibilityCanBePrivate")
package org.jetbrains.compose.web.css
interface CSSMediaQuery {
@ -9,12 +11,13 @@ interface CSSMediaQuery {
}
data class MediaType(val type: Enum) : Atomic {
enum class Enum {
all, print, screen, speech
All, Print, Screen, Speech
}
override fun toString() = type.name
}
@Suppress("EqualsOrHashCode")
data class MediaFeature(
val name: String,
val value: StylePropertyValue? = null
@ -55,6 +58,7 @@ interface CSSMediaQuery {
}
}
@Suppress("EqualsOrHashCode")
class CSSMediaRuleDeclaration(
val query: CSSMediaQuery,
rules: CSSRuleDeclarationList

14
web/core/src/jsMain/kotlin/androidx/compose/web/css/CSSOperations.kt

@ -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.
*/
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)

15
web/core/src/jsMain/kotlin/androidx/compose/web/css/CSSPolyfill.kt

@ -1,15 +0,0 @@
package org.jetbrains.compose.web.css
import org.w3c.dom.Window
@JsModule("css-typed-om")
@JsNonModule
abstract external class CSSTypedOMPolyfill {
companion object {
fun default(window: Window)
}
}
fun StylePropertyMap.clear() {
throw AssertionError("StylePropertyMap::clear isn't polyfilled")
}

219
web/core/src/jsMain/kotlin/androidx/compose/web/css/CSSProperties.kt

@ -1,5 +1,9 @@
@file:Suppress("Unused", "NOTHING_TO_INLINE")
package org.jetbrains.compose.web.css
import org.jetbrains.compose.web.css.keywords.CSSAutoKeyword
fun StyleBuilder.opacity(value: Number) {
property("opacity", value)
}
@ -17,7 +21,7 @@ fun StyleBuilder.flexShrink(value: Number) {
}
fun StyleBuilder.opacity(value: CSSSizeValue<CSSUnit.percent>) {
property("opacity", (value.value as Double / 100))
property("opacity", (value.value / 100))
}
fun StyleBuilder.color(value: String) {
@ -26,7 +30,7 @@ fun StyleBuilder.color(value: String) {
fun StyleBuilder.color(value: Color) {
// color hasn't Typed OM yet
property("color", value.styleValue())
property("color", value)
}
fun StyleBuilder.backgroundColor(value: CSSVariableValue<Color>) {
@ -34,196 +38,49 @@ fun StyleBuilder.backgroundColor(value: CSSVariableValue<Color>) {
}
fun StyleBuilder.backgroundColor(value: Color) {
property("background-color", value.styleValue())
property("background-color", value)
}
fun StyleBuilder.backgroundColor(value: String) {
property("background-color", value)
}
enum class LineStyle {
None,
Hidden,
Dotted,
Dashed,
Solid,
Double,
Groove,
Ridge,
Inset,
Outset
}
enum class DisplayStyle(val value: String) {
Block("block"),
Inline("inline"),
InlineBlock("inline-block"),
Flex("flex"),
LegacyInlineFlex("inline-flex"),
Grid("grid"),
LegacyInlineGrid("inline-grid"),
FlowRoot("flow-root"),
None("none"),
Contents("contents"),
// TODO(shabunc): This properties behave them iconsistenly in both Chrome and Firefox so I turned the off so far
// BlockFlow("block flow"),
// InlineFlow("inline flow"),
// InlineFlowRoot("inline flow-root"),
// BlocklFlex("block flex"),
// InlineFlex("inline flex"),
// BlockGrid("block grid"),
// InlineGrid("inline grid"),
// BlockFlowRoot("block flow-root"),
Table("table"),
TableRow("table-row"),
ListItem("list-item"),
Inherit("inherit"),
Initial("initial"),
Unset("unset")
}
enum class FlexDirection(val value: String) {
Row("row"),
RowReverse("row-reverse"),
Column("column"),
ColumnReverse("column-reverse")
}
enum class FlexWrap(val value: String) {
Wrap("wrap"),
Nowrap("nowrap"),
WrapReverse("wrap-reverse")
}
enum class JustifyContent(val value: String) {
Center("center"),
Start("start"),
End("end"),
FlexStart("flex-start"),
FlexEnd("flex-end"),
Left("left"),
Right("right"),
Normal("normal"),
SpaceBetween("space-between"),
SpaceAround("space-around"),
SpaceEvenly("space-evenly"),
Stretch("stretch"),
Inherit("inherit"),
Initial("initial"),
Unset("unset"),
SafeCenter("safe center"),
UnsafeCenter("unsafe center"),
}
enum class AlignSelf(val value: String) {
Auto("auto"),
Normal("normal"),
Center("center"),
Start("start"),
End("end"),
SelfStart("self-start"),
SelfEnd("self-end"),
FlexStart("flex-start"),
FlexEnd("flex-end"),
Baseline("baseline"),
// FirstBaseline("first baseline"),
// LastBaseline("last baseline"),
Stretch("stretch"),
SafeCenter("safe center"),
UnsafeCenter("unsafe center"),
Inherit("inherit"),
Initial("initial"),
Unset("unset")
}
enum class AlignItems(val value: String) {
Normal("normal"),
Stretch("stretch"),
Center("center"),
Start("start"),
End("end"),
FlexStart("flex-start"),
FlexEnd("flex-end"),
Baseline("baseline"),
// FirstBaseline("first baseline"),
// LastBaseline("last baseline"),
SafeCenter("safe center"),
UnsafeCenter("unsafe center"),
Inherit("inherit"),
Initial("initial"),
Unset("unset")
}
enum class AlignContent(val value: String) {
Center("center"),
Start("start"),
End("end"),
FlexStart("flex-start"),
FlexEnd("flex-end"),
Baseline("baseline"),
// FirstBaseline("first baseline"),
// LastBaseline("last baseline"),
SafeCenter("safe center"),
UnsafeCenter("unsafe center"),
SpaceBetween("space-between"),
SpaceAround("space-around"),
SpaceEvenly("space-evenly"),
Stretch("stretch"),
Inherit("inherit"),
Initial("initial"),
Unset("unset")
}
enum class Position(val value: String) {
Static("static"),
Relative("relative"),
Absolute("absolute"),
Sticky("sticky"),
Fixed("fixed")
}
class CSSBorder : CustomStyleValue {
@Suppress("EqualsOrHashCode")
class CSSBorder : CSSStyleValue {
var width: CSSUnitValue? = null
var style: StylePropertyValue? = null
var color: StylePropertyValue? = null
fun width(size: CSSUnitValue) {
width = size
override fun equals(other: Any?): Boolean {
return if (other is CSSBorder) {
width == other.width && style == other.style && color == other.color
} else false
}
fun style(style: LineStyle) {
this.style = style.name.unsafeCast<StylePropertyValue>()
override fun toString(): String {
val values = listOfNotNull(width, style, color)
return values.joinToString(" ")
}
}
fun color(color: Color) {
this.color = color.styleValue()
}
inline fun CSSBorder.width(size: CSSUnitValue) {
width = size
}
fun color(color: CSSVariableValue<Color>) {
this.color = color
}
inline fun CSSBorder.style(style: LineStyle) {
this.style = CSSStyleValue(style.name)
}
override fun equals(other: Any?): Boolean {
return if (other is CSSBorder) {
styleValue().toString() == other.styleValue().toString()
} else false
}
inline fun CSSBorder.color(color: Color) {
this.color = color
}
override fun styleValue(): StylePropertyValue {
val values = listOfNotNull(width?.asString(), style, color)
return values.joinToString(" ").unsafeCast<StylePropertyValue>()
}
inline fun CSSBorder.color(color: CSSVariableValue<Color>) {
this.color = color
}
inline fun StyleBuilder.border(crossinline borderBuild: CSSBorder.() -> Unit) {
val border = CSSBorder().apply(borderBuild)
property("border", border.styleValue())
property("border", CSSBorder().apply(borderBuild))
}
fun StyleBuilder.border(
@ -296,7 +153,7 @@ fun StyleBuilder.borderRadius(r: CSSUnitValue) {
}
fun StyleBuilder.borderRadius(topLeft: CSSUnitValue, bottomRight: CSSUnitValue) {
property("border-radius", "${topLeft.asString()} ${bottomRight.asString()}")
property("border-radius", "$topLeft $bottomRight")
}
fun StyleBuilder.borderRadius(
@ -304,7 +161,7 @@ fun StyleBuilder.borderRadius(
topRightAndBottomLeft: CSSUnitValue,
bottomRight: CSSUnitValue
) {
property("border-radius", "${topLeft.asString()} ${topRightAndBottomLeft.asString()} ${bottomRight.asString()}")
property("border-radius", "$topLeft $topRightAndBottomLeft $bottomRight")
}
fun StyleBuilder.borderRadius(
@ -315,7 +172,7 @@ fun StyleBuilder.borderRadius(
) {
property(
"border-radius",
"${topLeft.asString()} ${topRight.asString()} ${bottomRight.asString()} ${bottomLeft.asString()}"
"$topLeft $topRight $bottomRight $bottomLeft"
)
}
@ -323,7 +180,7 @@ fun StyleBuilder.width(value: CSSUnitValue) {
property("width", value)
}
fun StyleBuilder.width(value: CSSAutoValue) {
fun StyleBuilder.width(value: CSSAutoKeyword) {
property("width", value)
}
@ -331,7 +188,7 @@ fun StyleBuilder.height(value: CSSUnitValue) {
property("height", value)
}
fun StyleBuilder.height(value: CSSAutoValue) {
fun StyleBuilder.height(value: CSSAutoKeyword) {
property("height", value)
}
@ -339,7 +196,7 @@ fun StyleBuilder.top(value: CSSLengthOrPercentageValue) {
property("top", value)
}
fun StyleBuilder.top(value: CSSAutoValue) {
fun StyleBuilder.top(value: CSSAutoKeyword) {
property("top", value)
}
@ -347,7 +204,7 @@ fun StyleBuilder.bottom(value: CSSLengthOrPercentageValue) {
property("bottom", value)
}
fun StyleBuilder.bottom(value: CSSAutoValue) {
fun StyleBuilder.bottom(value: CSSAutoKeyword) {
property("bottom", value)
}
@ -355,7 +212,7 @@ fun StyleBuilder.left(value: CSSLengthOrPercentageValue) {
property("left", value)
}
fun StyleBuilder.left(value: CSSAutoValue) {
fun StyleBuilder.left(value: CSSAutoKeyword) {
property("left", value)
}
@ -363,7 +220,7 @@ fun StyleBuilder.right(value: CSSLengthOrPercentageValue) {
property("right", value)
}
fun StyleBuilder.right(value: CSSAutoValue) {
fun StyleBuilder.right(value: CSSAutoKeyword) {
property("right", value)
}

259
web/core/src/jsMain/kotlin/androidx/compose/web/css/CSSUnits.kt

@ -1,180 +1,173 @@
@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
interface CSSSizeValue<out T : CSSUnit> : StylePropertyValue {
external interface CSSNumericValue<T : CSSUnit> : StylePropertyValue
external interface CSSSizeValue<T : CSSUnit> : CSSNumericValue<T> {
val value: Float
val unit: T
fun asString(): String = "${value}${unit.value}"
fun newUnit(value: Float): CSSSizeValue<T>
}
private data class CSSUnitValueTyped<out T : CSSUnit>(
data class CSSUnitValueTyped<T : CSSUnit>(
override val value: Float,
override val unit: T
) : CSSSizeValue<T> {
override fun newUnit(value: Float): CSSSizeValue<T> = copy(value = value)
override fun toString(): String = asString()
override fun toString(): String = "$value$unit"
}
operator fun <T : CSSUnit> CSSSizeValue<T>.times(num: Number): CSSSizeValue<T> = newUnit(value * num.toFloat())
operator fun <T : CSSUnit> Number.times(unit: CSSSizeValue<T>): CSSSizeValue<T> = unit.newUnit(unit.value * toFloat())
operator fun <T : CSSUnit> CSSSizeValue<T>.div(num: Number): CSSSizeValue<T> = newUnit(value / num.toFloat())
operator fun <T: CSSUnit> CSSSizeValue<T>.plus(b: CSSSizeValue<T>): CSSSizeValue<T> = newUnit(value + b.value)
operator fun <T: CSSUnit> CSSSizeValue<T>.minus(b: CSSSizeValue<T>): CSSSizeValue<T> = newUnit(value - b.value)
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<CSSUnitAngle>
typealias CSSLengthOrPercentageValue = CSSSizeValue<CSSUnitLengthOrPercentage>
typealias CSSLengthValue = CSSSizeValue<CSSUnitLength>
typealias CSSPercentageValue = CSSSizeValue<CSSUnitPercentage>
typealias CSSUnitValue = CSSSizeValue<CSSUnit>
external interface CSSUnitLengthOrPercentage: CSSUnit
external interface CSSUnitPercentage: CSSUnitLengthOrPercentage
external interface CSSUnitLength: CSSUnitLengthOrPercentage
external interface CSSUnitRel : CSSUnitLength
external interface CSSUnitAbs: CSSUnitLength
external interface CSSUnitAngle: CSSUnit
external interface CSSUnitTime: CSSUnit
external interface CSSUnitFrequency: CSSUnit
external interface CSSUnitResolution: CSSUnit
external 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 CSSpxValue = CSSSizeValue<CSSUnit.px>
// fake interfaces to distinguish units
external interface CSSUnit {
external interface percent: CSSUnitPercentage
sealed interface CSSUnit {
val value: String
external interface em: CSSUnitRel
object percent: CSSUnitPercentage {
override val value: String = "%"
}
external interface ex: CSSUnitRel
object em: CSSUnitRel {
override val value = "em"
}
external interface ch: CSSUnitRel
object ex: CSSUnitRel {
override val value = "ex"
}
external interface ic: CSSUnitRel
object ch: CSSUnitRel {
override val value = "ch"
}
external interface rem: CSSUnitRel
object ic: CSSUnitRel {
override val value = "ic"
}
external interface lh: CSSUnitRel
object rem: CSSUnitRel {
override val value = "rem"
}
external interface rlh: CSSUnitRel
object lh: CSSUnitRel {
override val value = "lh"
}
external interface vw: CSSUnitRel
object rlh: CSSUnitRel {
override val value = "rlh"
}
external interface vh: CSSUnitRel
object vw: CSSUnitRel {
override val value = "vw"
}
external interface vi: CSSUnitRel
object vh: CSSUnitRel {
override val value = "vh"
}
external interface vb: CSSUnitRel
object vi: CSSUnitRel {
override val value = "vi"
}
external interface vmin: CSSUnitRel
object vb: CSSUnitRel {
override val value = "vb"
}
external interface vmax: CSSUnitRel
object vmin: CSSUnitRel {
override val value = "vmin"
}
external interface cm: CSSUnitRel
object vmax: CSSUnitRel {
override val value = "vmax"
}
external interface mm: CSSUnitRel
object cm: CSSUnitRel {
override val value = "cm"
}
external interface Q: CSSUnitRel
object mm: CSSUnitRel {
override val value = "mm"
}
external interface pt: CSSUnitAbs
object q: CSSUnitRel {
override val value = "q"
}
external interface pc: CSSUnitAbs
object pt: CSSUnitAbs {
override val value = "pt"
}
external interface px: CSSUnitAbs
object pc: CSSUnitAbs {
override val value = "pc"
}
external interface deg: CSSUnitAngle
object px: CSSUnitAbs {
override val value = "px"
}
external interface grad: CSSUnitAngle
object deg: CSSUnitAngle {
override val value = "deg"
}
external interface rad: CSSUnitAngle
object grad: CSSUnitAngle {
override val value = "grad"
}
external interface turn: CSSUnitAngle
object rad: CSSUnitAngle {
override val value = "rad"
}
external interface s: CSSUnitTime
object turn: CSSUnitAngle {
override val value = "turn"
}
external interface ms: CSSUnitTime
object s: CSSUnitTime {
override val value = "s"
}
external interface Hz: CSSUnitFrequency
object ms: CSSUnitTime {
override val value = "ms"
}
external interface kHz: CSSUnitFrequency
object hz: CSSUnitFrequency {
override val value = "hz"
}
external interface dpi: CSSUnitResolution
object khz: CSSUnitFrequency {
override val value = "khz"
}
external interface dpcm: CSSUnitResolution
object dpi: CSSUnitResolution {
override val value = "dpi"
}
external interface dppx: CSSUnitResolution
object dpcm: CSSUnitResolution {
override val value = "dpcm"
}
external interface fr: CSSUnitFlex
object dppx: CSSUnitResolution {
override val value = "dppx"
}
external interface number: CSSUnit
external companion object {
inline val percent get() = "%".unsafeCast<percent>()
object fr: CSSUnitFlex {
override val value = "fr"
}
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>()
object number: CSSUnit {
override val value = "number"
inline val number get() = "number".unsafeCast<number>()
}
}
@ -216,7 +209,7 @@ val Number.mm
get(): CSSSizeValue<CSSUnit.mm> = CSSUnitValueTyped(this.toFloat(), CSSUnit.mm)
val Number.Q
get() : CSSSizeValue<CSSUnit.q> = CSSUnitValueTyped(this.toFloat(), CSSUnit.q)
get() : CSSSizeValue<CSSUnit.Q> = CSSUnitValueTyped(this.toFloat(), CSSUnit.Q)
val Number.pt
get(): CSSSizeValue<CSSUnit.pt> = CSSUnitValueTyped(this.toFloat(), CSSUnit.pt)
@ -240,9 +233,9 @@ val Number.ms
get(): CSSSizeValue<CSSUnit.ms> = CSSUnitValueTyped(this.toFloat(), CSSUnit.ms)
val Number.Hz
get(): CSSSizeValue<CSSUnit.hz> = CSSUnitValueTyped(this.toFloat(), CSSUnit.hz)
get(): CSSSizeValue<CSSUnit.Hz> = CSSUnitValueTyped(this.toFloat(), CSSUnit.Hz)
val Number.kHz
get(): CSSSizeValue<CSSUnit.khz> = CSSUnitValueTyped(this.toFloat(), CSSUnit.khz)
get(): CSSSizeValue<CSSUnit.kHz> = CSSUnitValueTyped(this.toFloat(), CSSUnit.kHz)
val Number.dpi
get(): CSSSizeValue<CSSUnit.dpi> = CSSUnitValueTyped(this.toFloat(), CSSUnit.dpi)

15
web/core/src/jsMain/kotlin/androidx/compose/web/css/Color.kt

@ -1,8 +1,8 @@
package org.jetbrains.compose.web.css
@file:Suppress("unused", "MemberVisibilityCanBePrivate")
abstract class Color : CustomStyleValue {
override fun styleValue(): StylePropertyValue = toString().unsafeCast<StylePropertyValue>()
package org.jetbrains.compose.web.css
abstract class Color : CSSStyleValue {
data class Named(val value: String) : Color() {
override fun toString(): String = value
}
@ -18,16 +18,15 @@ abstract class Color : CustomStyleValue {
data class HSL(val h: CSSAngleValue, val s: Number, val l: Number) : Color() {
constructor(h: Number, s: Number, l: Number) : this(h.deg, s, l)
override fun toString(): String = "hsl(${h.asString()}, $s%, $l%)"
override fun toString(): String = "hsl($h, $s%, $l%)"
}
data class HSLA(val h: CSSAngleValue, val s: Number, val l: Number, val a: Number) : Color() {
constructor(h: Number, s: Number, l: Number, a: Number) : this(h.deg, s, l, a)
override fun toString(): String = "hsla(${h.asString()}, $s%, $l%, $a)"
override fun toString(): String = "hsla($h, $s%, $l%, $a)"
}
companion object {
operator fun invoke(name: String) = Named(name)
}
}
fun Color(name: String): Color = Color.Named(name)

87
web/core/src/jsMain/kotlin/androidx/compose/web/css/StyleBuilder.kt

@ -1,3 +1,10 @@
/*
* 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 kotlin.properties.ReadOnlyProperty
@ -6,37 +13,41 @@ interface StyleBuilder {
fun property(propertyName: String, value: StylePropertyValue)
fun variable(variableName: String, value: StylePropertyValue)
fun property(propertyName: String, value: String) = property(propertyName, value.unsafeCast<StylePropertyValue>())
fun property(propertyName: String, value: Number) = property(propertyName, value.unsafeCast<StylePropertyValue>())
fun variable(variableName: String, value: Number) = variable(variableName, value.unsafeCast<StylePropertyValue>())
fun variable(variableName: String, value: String) = variable(variableName, value.unsafeCast<StylePropertyValue>())
operator fun <TValue> CSSStyleVariable<TValue>.invoke(value: TValue) {
if (value is CustomStyleValue) {
variable(name, value.styleValue())
} else {
variable(name, value.toString())
}
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())
}
}
fun variableValue(variableName: String, fallback: StylePropertyValue? = null) =
"var(--$variableName${fallback?.let { ", $it" } ?: ""})"
operator fun CSSStyleVariable<StylePropertyString>.invoke(value: String) {
variable(name, value)
}
interface CSSVariableValue<TValue> : StylePropertyValue {
companion object {
operator fun <TValue> invoke(value: String) =
value.unsafeCast<CSSVariableValue<TValue>>()
operator fun <TValue> invoke(value: Number) =
value.unsafeCast<CSSVariableValue<TValue>>()
operator fun <TValue : CSSStyleValue> invoke(value: TValue) =
value.unsafeCast<CSSVariableValue<TValue>>()
operator fun <TValue> invoke(value: StylePropertyValue) =
value.unsafeCast<CSSVariableValue<TValue>>()
operator fun CSSStyleVariable<StylePropertyNumber>.invoke(value: Number) {
variable(name, value)
}
}
inline fun variableValue(variableName: String, fallback: StylePropertyValue? = null) =
"var(--$variableName${fallback?.let { ", $it" } ?: ""})"
external interface CSSVariableValue<TValue> : StylePropertyValue
inline fun <TValue> CSSVariableValue(value: String) =
StylePropertyValue(value).unsafeCast<CSSVariableValue<TValue>>()
//fun <TValue> CSSVariableValue(value: Number) =
// value.unsafeCast<CSSVariableValue<TValue>>()
//
//fun <TValue : CSSStyleValue> CSSVariableValue(value: TValue) =
// value.unsafeCast<CSSVariableValue<TValue>>()
//
//fun <TValue> CSSVariableValue(value: StylePropertyValue) =
// value.unsafeCast<CSSVariableValue<TValue>>()
// after adding `variable` word `add` became ambiguous
@Deprecated(
"use property instead, will remove it soon",
@ -53,24 +64,17 @@ interface CSSVariable {
val name: String
}
interface CustomStyleValue {
fun styleValue(): StylePropertyValue
}
data class CSSStyleVariable<TValue>(override val name: String) : CSSVariable
class CSSStyleVariable<out TValue: StylePropertyValue>(override val name: String) : CSSVariable
fun <TValue> CSSStyleVariable<TValue>.value(fallback: TValue? = null) =
fun <TValue: StylePropertyValue> CSSStyleVariable<TValue>.value(fallback: TValue? = null) =
CSSVariableValue<TValue>(
variableValue(
name,
fallback?.let {
(fallback as? CustomStyleValue)?.styleValue()
?: fallback.toString().unsafeCast<StylePropertyValue>()
}
fallback
)
)
fun <TValue> CSSVariables.variable() =
fun <TValue: StylePropertyValue> CSSVariables.variable() =
ReadOnlyProperty<Any?, CSSStyleVariable<TValue>> { _, property ->
CSSStyleVariable(property.name)
}
@ -80,22 +84,17 @@ interface StyleHolder {
val variables: StylePropertyList
}
@Suppress("EqualsOrHashCode")
open class StyleBuilderImpl : StyleBuilder, StyleHolder {
override val properties: MutableStylePropertyList = mutableListOf()
override val variables: MutableStylePropertyList = mutableListOf()
override fun property(propertyName: String, value: StylePropertyValue) {
properties.add(when (value) {
is CSSSizeValue<*> -> StylePropertyDeclaration(propertyName, value.asString())
else -> StylePropertyDeclaration(propertyName, value)
})
properties.add(StylePropertyDeclaration(propertyName, value))
}
override fun variable(variableName: String, value: StylePropertyValue) {
variables.add(when (value) {
is CSSSizeValue<*> -> StylePropertyDeclaration(variableName, value.asString())
else -> StylePropertyDeclaration(variableName, value)
})
variables.add(StylePropertyDeclaration(variableName, value))
}
// StylePropertyValue is js native object without equals

27
web/core/src/jsMain/kotlin/androidx/compose/web/css/StylePropertyValue.kt

@ -0,0 +1,27 @@
/*
* 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
external interface StylePropertyValue
external interface StylePropertyNumber: StylePropertyValue
external interface StylePropertyString: StylePropertyValue
inline fun StylePropertyValue(value: String): StylePropertyString = value.unsafeCast<StylePropertyString>()
inline fun StylePropertyValue(value: Number): StylePropertyNumber = value.unsafeCast<StylePropertyNumber>()
fun StylePropertyValue.asString(): String? = if (jsTypeOf(this) == "string") this.unsafeCast<String>() else null
fun StylePropertyValue.asNumber(): Number? = if (jsTypeOf(this) == "number") this.unsafeCast<Number>() else null
fun StylePropertyValue.asCSSStyleValue(): CSSStyleValue? = if (jsTypeOf(this) == "object") this.unsafeCast<CSSStyleValue>() else null
external interface CSSStyleValue: StylePropertyValue {
override fun toString(): String
}
inline fun CSSStyleValue(value: String): CSSStyleValue = StylePropertyValue(value).unsafeCast<CSSStyleValue>()

14
web/core/src/jsMain/kotlin/androidx/compose/web/css/keywords/Keywords.kt

@ -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.
*/
package org.jetbrains.compose.web.css.keywords
import org.jetbrains.compose.web.css.CSSKeywordValue
external interface CSSAutoKeyword : CSSKeywordValue
inline val auto: CSSAutoKeyword
get() = CSSKeywordValue("auto").unsafeCast<CSSAutoKeyword>()

2
web/core/src/jsMain/kotlin/androidx/compose/web/css/selectors/CSSSelectors.kt

@ -1,3 +1,5 @@
@file:Suppress("EqualsOrHashCode", "unused", "MemberVisibilityCanBePrivate")
package org.jetbrains.compose.web.css.selectors
import org.jetbrains.compose.web.css.LanguageCode

8
web/core/src/jsMain/kotlin/androidx/compose/web/elements/Style.kt

@ -29,7 +29,7 @@ inline fun Style(
* Use this function to mount the <style> tag into the DOM tree.
*
* @param cssRules - is a list of style rules.
* Usually, it's [org.jetbrains.compose.web.css.StyleSheet] instance
* Usually, it's [androidx.compose.web.css.StyleSheet] instance
*/
@Composable
inline fun Style(
@ -93,7 +93,7 @@ private fun fillRule(
is CSSStyleRuleDeclaration -> {
val cssStyleRule = cssRule.unsafeCast<CSSStyleRule>()
cssRuleDeclaration.style.properties.forEach { (name, value) ->
setProperty(cssStyleRule.styleMap, name, value)
setProperty(cssStyleRule.style, name, value)
}
cssRuleDeclaration.style.variables.forEach { (name, value) ->
setVariable(cssStyleRule.style, name, value)
@ -109,11 +109,11 @@ private fun fillRule(
}
fun setProperty(
styleMap: StylePropertyMap,
style: CSSStyleDeclaration,
name: String,
value: StylePropertyValue
) {
styleMap.set(name, value)
style.setProperty(name, value.toString())
}
fun setVariable(

116
web/core/src/jsTest/kotlin/CSSEnums.kt

@ -0,0 +1,116 @@
package org.jetbrains.compose.web.core.tests
import org.jetbrains.compose.web.css.*
fun DisplayStyle.Companion.values() = listOf(
DisplayStyle.Block,
DisplayStyle.Inline,
DisplayStyle.InlineBlock,
DisplayStyle.Flex,
DisplayStyle.LegacyInlineFlex,
DisplayStyle.Grid,
DisplayStyle.LegacyInlineGrid,
DisplayStyle.FlowRoot,
DisplayStyle.None,
DisplayStyle.Contents,
DisplayStyle.Table,
DisplayStyle.TableRow,
DisplayStyle.ListItem,
DisplayStyle.Inherit,
DisplayStyle.Initial,
DisplayStyle.Unset
)
fun FlexDirection.Companion.values() = listOf(
FlexDirection.Row,
FlexDirection.RowReverse,
FlexDirection.Column,
FlexDirection.ColumnReverse
)
fun FlexWrap.Companion.values() = listOf(
FlexWrap.Wrap,
FlexWrap.Nowrap,
FlexWrap.WrapReverse
)
fun JustifyContent.Companion.values() = listOf(
JustifyContent.Center,
JustifyContent.Start,
JustifyContent.End,
JustifyContent.FlexStart,
JustifyContent.FlexEnd,
JustifyContent.Left,
JustifyContent.Right,
JustifyContent.Normal,
JustifyContent.SpaceBetween,
JustifyContent.SpaceAround,
JustifyContent.SpaceEvenly,
JustifyContent.Stretch,
JustifyContent.Inherit,
JustifyContent.Initial,
JustifyContent.Unset,
JustifyContent.SafeCenter,
JustifyContent.UnsafeCenter
)
fun AlignSelf.Companion.values() = listOf(
AlignSelf.Auto,
AlignSelf.Normal,
AlignSelf.Center,
AlignSelf.Start,
AlignSelf.End,
AlignSelf.SelfStart,
AlignSelf.SelfEnd,
AlignSelf.FlexStart,
AlignSelf.FlexEnd,
AlignSelf.Baseline,
AlignSelf.Stretch,
AlignSelf.SafeCenter,
AlignSelf.UnsafeCenter,
AlignSelf.Inherit,
AlignSelf.Initial,
AlignSelf.Unset
)
fun AlignItems.Companion.values() = listOf(
AlignItems.Normal,
AlignItems.Stretch,
AlignItems.Center,
AlignItems.Start,
AlignItems.End,
AlignItems.FlexStart,
AlignItems.FlexEnd,
AlignItems.Baseline,
AlignItems.SafeCenter,
AlignItems.UnsafeCenter,
AlignItems.Inherit,
AlignItems.Initial,
AlignItems.Unset
)
fun AlignContent.Companion.values() = listOf(
AlignContent.Center,
AlignContent.Start,
AlignContent.End,
AlignContent.FlexStart,
AlignContent.FlexEnd,
AlignContent.Baseline,
AlignContent.SafeCenter,
AlignContent.UnsafeCenter,
AlignContent.SpaceBetween,
AlignContent.SpaceAround,
AlignContent.SpaceEvenly,
AlignContent.Stretch,
AlignContent.Inherit,
AlignContent.Initial,
AlignContent.Unset
)
fun Position.Companion.values() = listOf(
Position.Static,
Position.Relative,
Position.Absolute,
Position.Sticky,
Position.Fixed
)

4
web/core/src/jsTest/kotlin/CSSStylesheetTests.kt

@ -16,8 +16,8 @@ object AppCSSVariables : CSSVariables {
val width by variable<CSSUnitValue>()
val height by variable<CSSUnitValue>()
val stringWidth by variable<String>()
val stringHeight by variable<String>()
val stringWidth by variable<StylePropertyString>()
val stringHeight by variable<StylePropertyString>()
}
object AppStylesheet : StyleSheet() {

48
web/core/src/jsTest/kotlin/CSSUnitApiTests.kt

@ -51,40 +51,40 @@ class CSSUnitApiTests {
@Test
fun postfixInvocation() {
// TODO: review what exactly number does - most likely we don't need it in our ecosystem
assertEquals("4number", 4.number.asString())
assertEquals("4number", 4.number.toString())
assertEquals("4%", 4.percent.asString())
assertEquals("4%", 4.percent.toString())
assertEquals("4em", 4.em.asString())
assertEquals("4ch", 4.ch.asString())
assertEquals("4em", 4.em.toString())
assertEquals("4ch", 4.ch.toString())
assertEquals("4rem", 4.cssRem.asString())
assertEquals("4rem", 4.cssRem.toString())
assertEquals("4vw", 4.vw.asString())
assertEquals("4vh", 4.vh.asString())
assertEquals("4vw", 4.vw.toString())
assertEquals("4vh", 4.vh.toString())
assertEquals("4vmin", 4.vmin.asString())
assertEquals("4vmax", 4.vmax.asString())
assertEquals("4cm", 4.cm.asString())
assertEquals("4mm", 4.mm.asString())
assertEquals("4vmin", 4.vmin.toString())
assertEquals("4vmax", 4.vmax.toString())
assertEquals("4cm", 4.cm.toString())
assertEquals("4mm", 4.mm.toString())
assertEquals("4pt", 4.pt.asString())
assertEquals("4pc", 4.pc.asString())
assertEquals("4px", 4.px.asString())
assertEquals("4pt", 4.pt.toString())
assertEquals("4pc", 4.pc.toString())
assertEquals("4px", 4.px.toString())
assertEquals("4deg", 4.deg.asString())
assertEquals("4grad", 4.grad.asString())
assertEquals("4rad", 4.rad.asString())
assertEquals("4turn", 4.turn.asString())
assertEquals("4deg", 4.deg.toString())
assertEquals("4grad", 4.grad.toString())
assertEquals("4rad", 4.rad.toString())
assertEquals("4turn", 4.turn.toString())
assertEquals("4s", 4.s.asString())
assertEquals("4ms", 4.ms.asString())
assertEquals("4s", 4.s.toString())
assertEquals("4ms", 4.ms.toString())
assertEquals("4dpi", 4.dpi.asString())
assertEquals("4dpcm", 4.dpcm.asString())
assertEquals("4dppx", 4.dppx.asString())
assertEquals("4dpi", 4.dpi.toString())
assertEquals("4dpcm", 4.dpcm.toString())
assertEquals("4dppx", 4.dppx.toString())
assertEquals("4fr", 4.fr.asString())
assertEquals("4fr", 4.fr.toString())
}
@Test

1
web/core/src/jsTest/kotlin/InlineStyleTests.kt

@ -4,6 +4,7 @@ import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import org.jetbrains.compose.web.css.*
import org.jetbrains.compose.web.css.keywords.auto
import org.jetbrains.compose.web.dom.Span
import org.jetbrains.compose.web.dom.Text
import kotlin.test.Test

27
web/core/src/jsTest/kotlin/StaticComposableTests.kt

@ -134,14 +134,15 @@ class StaticComposableTests {
}
assertEquals("border: 1px solid red;", (root.children[0] as HTMLElement).style.cssText)
root.children[1]?.let { el ->
root.children[1]?.let {
val el = it.unsafeCast<HTMLElement>()
assertEquals(
"green",
el.asDynamic().attributeStyleMap.get("border-color").toString(),
el.style.getPropertyValue("border-color")
)
assertEquals(
"3px",
el.asDynamic().attributeStyleMap.get("border-width").toString(),
el.style.getPropertyValue("border-width"),
)
}
}
@ -444,7 +445,7 @@ class StaticComposableTests {
@Test
fun stylesDisplay() {
val root = "div".asHtmlElement()
val enumValues = enumValues<DisplayStyle>()
val enumValues = DisplayStyle.values()
renderComposable(
root = root
) {
@ -470,7 +471,7 @@ class StaticComposableTests {
@Test
fun stylesFlexDirection() {
val root = "div".asHtmlElement()
val enumValues = enumValues<FlexDirection>()
val enumValues = FlexDirection.values()
renderComposable(
root = root
) {
@ -496,7 +497,7 @@ class StaticComposableTests {
@Test
fun stylesFlexWrap() {
val root = "div".asHtmlElement()
val enumValues = enumValues<FlexWrap>()
val enumValues = FlexWrap.values()
renderComposable(
root = root
) {
@ -522,8 +523,8 @@ class StaticComposableTests {
@Test
fun stylesFlexFlow() {
val root = "div".asHtmlElement()
val flexWraps = enumValues<FlexWrap>()
val flexDirections = enumValues<FlexDirection>()
val flexWraps = FlexWrap.values()
val flexDirections = FlexDirection.values()
renderComposable(
root = root
) {
@ -553,7 +554,7 @@ class StaticComposableTests {
@Test
fun stylesJustifyContent() {
val root = "div".asHtmlElement()
val enumValues = enumValues<JustifyContent>()
val enumValues = JustifyContent.values()
renderComposable(
root = root
) {
@ -579,7 +580,7 @@ class StaticComposableTests {
@Test
fun stylesAlignSelf() {
val root = "div".asHtmlElement()
val enumValues = enumValues<AlignSelf>()
val enumValues = AlignSelf.values()
renderComposable(
root = root
) {
@ -605,7 +606,7 @@ class StaticComposableTests {
@Test
fun stylesAlignItems() {
val root = "div".asHtmlElement()
val enumValues = enumValues<AlignItems>()
val enumValues = AlignItems.values()
renderComposable(
root = root
) {
@ -631,7 +632,7 @@ class StaticComposableTests {
@Test
fun stylesAlignContent() {
val root = "div".asHtmlElement()
val enumValues = enumValues<AlignContent>()
val enumValues = AlignContent.values()
renderComposable(
root = root
) {
@ -657,7 +658,7 @@ class StaticComposableTests {
@Test
fun stylesPosition() {
val root = "div".asHtmlElement()
val enumValues = enumValues<Position>()
val enumValues = Position.values()
renderComposable(
root = root
) {

24
web/integration-core/src/jsMain/kotlin/androidx/compose/web/sample/Sample.kt

@ -11,30 +11,9 @@ import androidx.compose.runtime.setValue
import org.jetbrains.compose.web.attributes.Draggable
import org.jetbrains.compose.web.attributes.InputType
import org.jetbrains.compose.web.attributes.name
import org.jetbrains.compose.web.css.CSSVariables
import org.jetbrains.compose.web.css.Color
import org.jetbrains.compose.web.css.LineStyle
import org.jetbrains.compose.web.css.Style
import org.jetbrains.compose.web.css.StyleSheet
import org.jetbrains.compose.web.css.and
import org.jetbrains.compose.web.css.backgroundColor
import org.jetbrains.compose.web.css.border
import org.jetbrains.compose.web.css.color
import org.jetbrains.compose.web.css.fontSize
import org.jetbrains.compose.web.css.margin
import org.jetbrains.compose.web.css.maxWidth
import org.jetbrains.compose.web.css.media
import org.jetbrains.compose.web.css.minWidth
import org.jetbrains.compose.web.css.opacity
import org.jetbrains.compose.web.css.padding
import org.jetbrains.compose.web.css.percent
import org.jetbrains.compose.web.css.px
import org.jetbrains.compose.web.css.selectors.className
import org.jetbrains.compose.web.css.selectors.hover
import org.jetbrains.compose.web.css.selectors.plus
import org.jetbrains.compose.web.css.value
import org.jetbrains.compose.web.css.variable
import org.jetbrains.compose.web.css.width
import org.jetbrains.compose.web.dom.A
import org.jetbrains.compose.web.dom.Button
import org.jetbrains.compose.web.dom.Div
@ -48,6 +27,7 @@ import kotlinx.browser.window
import kotlinx.coroutines.MainScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import org.jetbrains.compose.web.css.*
import org.w3c.dom.url.URLSearchParams
class State {
@ -59,7 +39,7 @@ val globalInt = mutableStateOf(1)
object MyCSSVariables : CSSVariables {
val myVar by variable<Color>()
val myVar2 by variable<String>()
val myVar2 by variable<StylePropertyString>()
}
object AppStyleSheet : StyleSheet() {

1
web/widgets/src/jsMain/kotlin/Modifier.kt

@ -7,7 +7,6 @@ import org.jetbrains.compose.web.css.margin
import org.jetbrains.compose.web.css.px
import org.jetbrains.compose.web.css.Color.RGB
import org.jetbrains.compose.common.internal.castOrCreate
import org.jetbrains.compose.web.css.StyleBuilder
import org.jetbrains.compose.web.attributes.AttrsBuilder
actual fun Modifier.background(color: Color): Modifier = castOrCreate().apply {

Loading…
Cancel
Save