Browse Source

fix Style composable and CSSRulesHolderState (#1889)

Co-authored-by: Oleksandr Karpovich <oleksandr.karpovich@jetbrains.com>
pull/1770/merge
Oleksandr Karpovich 3 years ago committed by GitHub
parent
commit
1ab63ed995
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      examples/web-landing/src/jsMain/kotlin/com/sample/content/CodeSnippets.kt
  2. 1
      examples/web-landing/src/jsMain/kotlin/com/sample/content/IntroSection.kt
  3. 11
      web/core/src/jsMain/kotlin/org/jetbrains/compose/web/css/StyleSheet.kt
  4. 2
      web/core/src/jsMain/kotlin/org/jetbrains/compose/web/elements/Elements.kt
  5. 77
      web/core/src/jsTest/kotlin/CSSStylesheetTests.kt

1
examples/web-landing/src/jsMain/kotlin/com/sample/content/CodeSnippets.kt

@ -263,6 +263,7 @@ fun FormattedCodeSnippet(code: String, language: String = "kotlin") {
backgroundColor(Color("transparent")) backgroundColor(Color("transparent"))
} }
}) { }) {
@Suppress("DEPRECATION")
DomSideEffect(code) { DomSideEffect(code) {
it.setHighlightedCode(code) it.setHighlightedCode(code)
} }

1
examples/web-landing/src/jsMain/kotlin/com/sample/content/IntroSection.kt

@ -2,7 +2,6 @@ package com.sample.content
import androidx.compose.runtime.* import androidx.compose.runtime.*
import org.jetbrains.compose.web.attributes.ATarget import org.jetbrains.compose.web.attributes.ATarget
import org.jetbrains.compose.web.attributes.AttrsBuilder
import org.jetbrains.compose.web.attributes.target import org.jetbrains.compose.web.attributes.target
import org.jetbrains.compose.web.css.* import org.jetbrains.compose.web.css.*
import org.jetbrains.compose.web.dom.* import org.jetbrains.compose.web.dom.*

11
web/core/src/jsMain/kotlin/org/jetbrains/compose/web/css/StyleSheet.kt

@ -1,20 +1,19 @@
package org.jetbrains.compose.web.css package org.jetbrains.compose.web.css
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.getValue import org.jetbrains.compose.web.ExperimentalComposeWebStyleApi
import androidx.compose.runtime.setValue
import org.jetbrains.compose.web.css.selectors.CSSSelector import org.jetbrains.compose.web.css.selectors.CSSSelector
import org.jetbrains.compose.web.dom.Style import org.jetbrains.compose.web.dom.Style
import kotlin.properties.ReadOnlyProperty import kotlin.properties.ReadOnlyProperty
import kotlin.reflect.KProperty import kotlin.reflect.KProperty
class CSSRulesHolderState : CSSRulesHolder { class CSSRulesHolderState : CSSRulesHolder {
override var cssRules: CSSRuleDeclarationList by mutableStateOf(listOf()) override val cssRules = mutableStateListOf<CSSRuleDeclaration>()
override fun add(cssRule: CSSRuleDeclaration) { override fun add(cssRule: CSSRuleDeclaration) {
@Suppress("SuspiciousCollectionReassignment") cssRules.add(cssRule)
cssRules += cssRule
} }
} }

2
web/core/src/jsMain/kotlin/org/jetbrains/compose/web/elements/Elements.kt

@ -947,7 +947,7 @@ fun Style(
} }
}, },
) { ) {
DisposableEffect(cssRules) { DisposableEffect(cssRules, cssRules.size) {
val cssStylesheet = scopeElement.sheet as? CSSStyleSheet val cssStylesheet = scopeElement.sheet as? CSSStyleSheet
cssStylesheet?.setCSSRules(cssRules) cssStylesheet?.setCSSRules(cssRules)
onDispose { onDispose {

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

@ -5,12 +5,17 @@
package org.jetbrains.compose.web.core.tests package org.jetbrains.compose.web.core.tests
import androidx.compose.runtime.mutableStateOf
import org.jetbrains.compose.web.css.* import org.jetbrains.compose.web.css.*
import org.jetbrains.compose.web.dom.Div import org.jetbrains.compose.web.dom.Div
import org.jetbrains.compose.web.dom.stringPresentation import org.jetbrains.compose.web.dom.stringPresentation
import org.w3c.dom.HTMLElement import org.w3c.dom.HTMLElement
import org.w3c.dom.get import org.w3c.dom.get
import org.jetbrains.compose.web.testutils.* import org.jetbrains.compose.web.testutils.*
import org.w3c.dom.HTMLDivElement
import org.w3c.dom.HTMLStyleElement
import org.w3c.dom.css.CSSStyleSheet
import org.w3c.dom.css.get
import kotlin.test.* import kotlin.test.*
object AppCSSVariables { object AppCSSVariables {
@ -320,4 +325,76 @@ class CSSVariableTests {
} }
} }
} }
@Test
fun testChildStylesheetsGetApplied() = runTest {
val showContent = mutableStateOf(false)
composition {
Style(TestRootStylesheet2)
if (showContent.value) {
Div(attrs = {
classes(ChildStylesheet2.content)
}) {}
}
}
val styleElem = root.children[0] as HTMLStyleElement
val cssStyleSheet = styleElem.sheet as CSSStyleSheet
assertEquals(1, cssStyleSheet.cssRules.length)
assertEquals(".cls1 { padding: 10px; }", cssStyleSheet.cssRules[0]!!.cssText)
showContent.value = true
waitForRecompositionComplete()
with(root.children[1] as HTMLDivElement) {
assertEquals("content", getAttribute("class"))
}
// 2nd recomposition occurs since TestRootStylesheet2 was changed during recomposition
// when ChildStylesheet2 was initialised after showContent was set into "true"
waitForRecompositionComplete()
val styleElem2 = root.children[0] as HTMLStyleElement
val cssStyleSheet2 = styleElem2.sheet as CSSStyleSheet
assertEquals(".cls1 { padding: 10px; }", cssStyleSheet2.cssRules[0]!!.cssText)
assertEquals(2, cssStyleSheet2.cssRules.length)
assertEquals(".content { color: red; }", cssStyleSheet2.cssRules[1]!!.cssText)
}
@Test
fun testChildStylesheetsGetApplied2() = runTest {
composition {
Style(TestRootStylesheet)
Div(attrs = { classes(ChildStylesheet.content) })
}
val styleElem = root.children[0] as HTMLStyleElement
val cssStyleSheet = styleElem.sheet as CSSStyleSheet
assertEquals(2, cssStyleSheet.cssRules.length)
assertEquals(".cls1 { padding: 10px; }", cssStyleSheet.cssRules[0]!!.cssText)
assertEquals(".content { color: red; }", cssStyleSheet.cssRules[1]!!.cssText)
}
}
private object TestRootStylesheet : StyleSheet(usePrefix = false) {
val cls1 by style {
padding(10.px)
}
}
private object ChildStylesheet : StyleSheet(TestRootStylesheet, usePrefix = false) {
val content by style {
color(Color.red)
}
}
// Use duplicates for another test to ensure uninitialized objects will be used
private object TestRootStylesheet2 : StyleSheet(usePrefix = false) {
val cls1 by style {
padding(10.px)
}
}
private object ChildStylesheet2 : StyleSheet(TestRootStylesheet2, usePrefix = false) {
val content by style {
color(Color.red)
}
} }

Loading…
Cancel
Save