You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

280 lines
7.9 KiB

package com.sample.content
import androidx.compose.runtime.Composable
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.dom.*
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) {
innerText = code
HighlightJs.highlightElement(this)
}
private val SimpleCounterSnippet = CodeSnippetData(
title = "Simple Counter using Composable DOM",
source = """
fun main() {
val count = mutableStateOf(0)
renderComposable(rootElementId = "root") {
Button(attrs = {
onClick { count.value = count.value - 1 }
}) {
Text("-")
}
Span(style = { padding(15.px) }) { /* we use inline style here */
Text("${"$"}{count.value}")
}
Button(attrs = {
onClick { count.value = count.value + 1 }
}) {
Text("+")
}
}
}
""".trimIndent()
)
private val DeclareAndUseStylesheet = CodeSnippetData(
title = "Declare and use a stylesheet",
source = """
object MyStyleSheet : StyleSheet() {
val container by style { /* define a class `container` */
border(1.px, LineStyle.Solid, Color.RGB(255, 0, 0))
}
}
@Composable
fun MyComponent() {
Div(attrs = {
classes(MyStyleSheet.container) /* use `container` class */
}) {
Text("Hello world!")
}
}
fun main() {
renderComposable(rootElementId = "root") {
Style(MyStyleSheet) /* mount the stylesheet */
MyComponent()
}
}
""".trimIndent()
)
private val DeclareAndUseCssVariable = CodeSnippetData(
title = "Declare and use CSS variables",
source = """
object MyVariables : CSSVariables {
val contentBackgroundColor by variable<Color>() /* declare a variable */
}
object MyStyleSheet: StyleSheet() {
val container by style {
MyVariables.contentBackgroundColor(Color("blue")) /* set its value */
}
val content by style {
backgroundColor(MyVariables.contentBackgroundColor.value()) /* use it */
}
}
@Composable
fun MyComponent() {
Div(attrs = {
classes(MyStyleSheet.container)
}) {
Span(attrs = {
classes(MyStyleSheet.content)
}) {
Text("Hello world!")
}
}
}
""".trimIndent()
)
private val HoverSelectorAndMedia = CodeSnippetData(
title = "Hover selector and media query examples",
source = """
object MyStyleSheet: StyleSheet() {
val container by style {
backgroundColor(Color("blue"))
padding(20.px)
hover(self) style { /* `self` is a reference to the class */
backgroundColor(Color("red"))
}
media(maxWidth(500.px)) {
self style {
padding(10.px)
}
}
}
}
""".trimIndent()
)
private val DefineCssClassInComponent = CodeSnippetData(
title = "Define a CSS class in a component",
source = """
object MyStyleSheet: StyleSheet() {}
@Composable
fun MyComponent() {
Div(attrs = {
/* the class name will be generated at runtime */
classes(MyStyleSheet.css {
backgroundColor(Color("blue"))
self + ":hover" style { /* this is an example of a raw selector */
backgroundColor(Color("red"))
}
})
}) {
Text("Hello world!")
}
}
""".trimIndent()
)
private val LayoutsSample = CodeSnippetData(
title = "Counter for Web and Desktop",
source = """
/* Shared code in commonMain - App.kt (No direct control over DOM or CSS here) */
private val counter = mutableStateOf(0)
@Composable
fun App() {
Row {
Button(onClick = { counter.value = counter.value - 1 }) {
Text("-")
}
Text("${"$"}{counter.value}", modifier = Modifier.padding(16.dp))
Button(onClick = { counter.value = counter.value + 1 }) {
Text("+")
}
}
}
/* Desktop specific code in desktopMain: */
fun main() = Window(title = "Demo", size = IntSize(800, 800)) {
App()
}
/* Web specific code in jsMain: */
fun main() = renderComposable(rootElementId = "root") {
App()
}
""".trimIndent()
)
private val allSnippets = arrayOf(
SimpleCounterSnippet,
DeclareAndUseStylesheet,
DeclareAndUseCssVariable,
HoverSelectorAndMedia,
DefineCssClassInComponent,
LayoutsSample
)
private var currentCodeSnippet: CodeSnippetData by mutableStateOf(allSnippets[0])
private var selectedSnippetIx: Int by mutableStateOf(0)
@Composable
fun CodeSamples() {
ContainerInSection {
Div(attrs = {
classes(WtRows.wtRow)
style {
justifyContent(JustifyContent.SpaceBetween)
}
}) {
Div(attrs = { classes(WtCols.wtCol6, WtCols.wtColMd4, WtCols.wtColSm12) }) {
H1(attrs = {
classes(WtTexts.wtH2)
}) {
Text("Code samples")
}
}
Div(attrs = { classes(WtOffsets.wtTopOffsetSm24) }) {
CodeSampleSwitcher(count = allSnippets.size, current = selectedSnippetIx) {
selectedSnippetIx = it
currentCodeSnippet = allSnippets[it]
}
}
}
TitledCodeSample(title = currentCodeSnippet.title, code = currentCodeSnippet.source)
}
}
@Composable
private fun TitledCodeSample(title: String, code: String) {
H3(attrs = {
classes(WtTexts.wtH3, WtOffsets.wtTopOffset48)
}) {
Text(title)
}
Div(
attrs = {
classes(WtOffsets.wtTopOffset24)
style {
backgroundColor(Color.RGBA(39, 40, 44, 0.05))
borderRadius(8.px, 8.px, 8.px)
property("padding", "12px 16px")
}
}
) {
FormattedCodeSnippet(code = code)
}
}
@Composable
fun FormattedCodeSnippet(code: String, language: String = "kotlin") {
Pre(attrs = {
style {
property("max-height", 25.em)
property("overflow", "auto")
height(auto)
}
}) {
Code(
attrs = {
classes("language-$language", "hljs")
style {
property("font-family", "'JetBrains Mono', monospace")
property("tab-size", 4)
fontSize(10.pt)
backgroundColor(Color.transparent)
}
}
) {
DomSideEffect(code) {
it.setHighlightedCode(code)
}
}
}
}
private data class CodeSnippetData(
val title: String,
val source: String
)