summaryrefslogtreecommitdiff
path: root/src/main/kotlin/pl/treksoft/kvision
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/kotlin/pl/treksoft/kvision')
-rw-r--r--src/main/kotlin/pl/treksoft/kvision/Showcase.kt32
-rw-r--r--src/main/kotlin/pl/treksoft/kvision/core/StyledComponent.kt198
-rw-r--r--src/main/kotlin/pl/treksoft/kvision/core/Types.kt21
-rw-r--r--src/main/kotlin/pl/treksoft/kvision/core/Widget.kt37
-rw-r--r--src/main/kotlin/pl/treksoft/kvision/css/Css.kt62
-rw-r--r--src/main/kotlin/pl/treksoft/kvision/panel/SplitPanel.kt2
-rw-r--r--src/main/kotlin/pl/treksoft/kvision/utils/Utils.kt38
7 files changed, 325 insertions, 65 deletions
diff --git a/src/main/kotlin/pl/treksoft/kvision/Showcase.kt b/src/main/kotlin/pl/treksoft/kvision/Showcase.kt
index aa97a026..dc45e93b 100644
--- a/src/main/kotlin/pl/treksoft/kvision/Showcase.kt
+++ b/src/main/kotlin/pl/treksoft/kvision/Showcase.kt
@@ -4,7 +4,9 @@ import pl.treksoft.kvision.basic.Label
import pl.treksoft.kvision.core.Container
import pl.treksoft.kvision.core.Img
import pl.treksoft.kvision.core.Root
-import pl.treksoft.kvision.core.UNIT
+import pl.treksoft.kvision.css.BORDERSTYLE
+import pl.treksoft.kvision.css.Border
+import pl.treksoft.kvision.css.COLOR
import pl.treksoft.kvision.dropdown.DD.*
import pl.treksoft.kvision.dropdown.DropDown
import pl.treksoft.kvision.html.*
@@ -15,6 +17,7 @@ import pl.treksoft.kvision.modal.Confirm
import pl.treksoft.kvision.modal.Modal
import pl.treksoft.kvision.panel.*
import pl.treksoft.kvision.routing.routing
+import pl.treksoft.kvision.utils.px
class Showcase : ApplicationBase() {
@@ -76,12 +79,16 @@ class Showcase : ApplicationBase() {
split.add(tabs)
val split2 = SplitPanel(DIRECTION.HORIZONTAL)
- split2.add(Tag(TAG.DIV, "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce nec fringilla turpis, vel molestie dolor. Vestibulum ut ex eget orci porta gravida eu sit amet tortor. Suspendisse vel fermentum purus, vel ornare tellus. Vivamus dictum, risus non viverra venenatis, magna mi pharetra purus, nec dignissim risus tortor a sem. Donec tincidunt dui ut eros laoreet consectetur. Nam dapibus vestibulum sem, eget accumsan ex vestibulum ac. Curabitur ac mi sit amet eros sodales dictum. Sed at felis at nunc aliquam finibus. Vestibulum lorem nulla, dictum ac libero non, mattis dictum nisl. Aenean semper lorem turpis. Praesent pellentesque ligula est, viverra molestie leo imperdiet ut. Nam vitae hendrerit justo. Nullam tincidunt et nibh ac volutpat. Aliquam vulputate mi aliquam fermentum rhoncus.\n" +
+ val t1 = Tag(TAG.DIV, "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce nec fringilla turpis, vel molestie dolor. Vestibulum ut ex eget orci porta gravida eu sit amet tortor. Suspendisse vel fermentum purus, vel ornare tellus. Vivamus dictum, risus non viverra venenatis, magna mi pharetra purus, nec dignissim risus tortor a sem. Donec tincidunt dui ut eros laoreet consectetur. Nam dapibus vestibulum sem, eget accumsan ex vestibulum ac. Curabitur ac mi sit amet eros sodales dictum. Sed at felis at nunc aliquam finibus. Vestibulum lorem nulla, dictum ac libero non, mattis dictum nisl. Aenean semper lorem turpis. Praesent pellentesque ligula est, viverra molestie leo imperdiet ut. Nam vitae hendrerit justo. Nullam tincidunt et nibh ac volutpat. Aliquam vulputate mi aliquam fermentum rhoncus.\n" +
"\n" +
- "Proin porttitor diam id massa eleifend aliquet. Morbi nec erat porttitor, placerat lorem et, dignissim lectus. Cras ultricies posuere arcu, et pharetra dui laoreet in. Sed nec ipsum in sapien vestibulum maximus eu id nunc. Ut finibus aliquam nisi id vehicula. Phasellus sodales lobortis orci, non interdum risus dignissim quis. Proin bibendum consectetur diam nec mattis. Suspendisse dictum vulputate metus at tincidunt."))
- split2.add(Tag(TAG.DIV, "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce nec fringilla turpis, vel molestie dolor. Vestibulum ut ex eget orci porta gravida eu sit amet tortor. Suspendisse vel fermentum purus, vel ornare tellus. Vivamus dictum, risus non viverra venenatis, magna mi pharetra purus, nec dignissim risus tortor a sem. Donec tincidunt dui ut eros laoreet consectetur. Nam dapibus vestibulum sem, eget accumsan ex vestibulum ac. Curabitur ac mi sit amet eros sodales dictum. Sed at felis at nunc aliquam finibus. Vestibulum lorem nulla, dictum ac libero non, mattis dictum nisl. Aenean semper lorem turpis. Praesent pellentesque ligula est, viverra molestie leo imperdiet ut. Nam vitae hendrerit justo. Nullam tincidunt et nibh ac volutpat. Aliquam vulputate mi aliquam fermentum rhoncus.\n" +
+ "Proin porttitor diam id massa eleifend aliquet. Morbi nec erat porttitor, placerat lorem et, dignissim lectus. Cras ultricies posuere arcu, et pharetra dui laoreet in. Sed nec ipsum in sapien vestibulum maximus eu id nunc. Ut finibus aliquam nisi id vehicula. Phasellus sodales lobortis orci, non interdum risus dignissim quis. Proin bibendum consectetur diam nec mattis. Suspendisse dictum vulputate metus at tincidunt.")
+ t1.padding = 5.px()
+ split2.add(t1)
+ val t2 = Tag(TAG.DIV, "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce nec fringilla turpis, vel molestie dolor. Vestibulum ut ex eget orci porta gravida eu sit amet tortor. Suspendisse vel fermentum purus, vel ornare tellus. Vivamus dictum, risus non viverra venenatis, magna mi pharetra purus, nec dignissim risus tortor a sem. Donec tincidunt dui ut eros laoreet consectetur. Nam dapibus vestibulum sem, eget accumsan ex vestibulum ac. Curabitur ac mi sit amet eros sodales dictum. Sed at felis at nunc aliquam finibus. Vestibulum lorem nulla, dictum ac libero non, mattis dictum nisl. Aenean semper lorem turpis. Praesent pellentesque ligula est, viverra molestie leo imperdiet ut. Nam vitae hendrerit justo. Nullam tincidunt et nibh ac volutpat. Aliquam vulputate mi aliquam fermentum rhoncus.\n" +
"\n" +
- "Proin porttitor diam id massa eleifend aliquet. Morbi nec erat porttitor, placerat lorem et, dignissim lectus. Cras ultricies posuere arcu, et pharetra dui laoreet in. Sed nec ipsum in sapien vestibulum maximus eu id nunc. Ut finibus aliquam nisi id vehicula. Phasellus sodales lobortis orci, non interdum risus dignissim quis. Proin bibendum consectetur diam nec mattis. Suspendisse dictum vulputate metus at tincidunt."))
+ "Proin porttitor diam id massa eleifend aliquet. Morbi nec erat porttitor, placerat lorem et, dignissim lectus. Cras ultricies posuere arcu, et pharetra dui laoreet in. Sed nec ipsum in sapien vestibulum maximus eu id nunc. Ut finibus aliquam nisi id vehicula. Phasellus sodales lobortis orci, non interdum risus dignissim quis. Proin bibendum consectetur diam nec mattis. Suspendisse dictum vulputate metus at tincidunt.")
+ t2.padding = 10.px()
+ split2.add(t2)
split.add(split2)
root.add(split)
split.setEventListener<SplitPanel> {
@@ -94,6 +101,12 @@ class Showcase : ApplicationBase() {
val p = Tag(TAG.P, "To jest prawo", align = ALIGN.RIGHT)
p.title = "Tytuł"
+ p.border = Border(3.px(), BORDERSTYLE.SOLID)
+ p.borderTop = Border(4.px(), BORDERSTYLE.DASHED, COLOR.RED)
+ p.borderBottom = Border(4.px(), BORDERSTYLE.DASHED, 0x00ff00)
+ p.borderLeft = Border(4.px(), BORDERSTYLE.SOLID, 0xff00ff)
+ p.marginTop = 30.px()
+ p.paddingRight = 30.px()
root.add(p)
val del = Tag(TAG.DEL, "To jest deleted")
root.add(del)
@@ -162,13 +175,14 @@ class Showcase : ApplicationBase() {
dock.add(Label("up"), SIDE.UP)
dock.add(Label("down"), SIDE.DOWN)
dock.add(Label("center"), SIDE.CENTER)
+ dock.border = Border(7.px(), BORDERSTYLE.INSET, 0xdddddd)
// root.add(dock)
val pa = HPanel(alignItems = FLEXALIGNITEMS.FLEXEND)
- pa.add(Label("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce nec fringilla turpis, vel molestie dolor. Vestibulum ut ex eget orci porta gravida eu sit amet tortor. Suspendisse vel fermentum purus, vel ornare tellus. Vivamus dictum, risus non viverra venenatis, magna mi pharetra purus, nec dignissim risus tortor a sem. Donec tincidunt dui ut eros laoreet consectetur. Nam dapibus vestibulum sem, eget accumsan ex vestibulum ac. Curabitur ac mi sit amet eros sodales dictum. Sed at felis at nunc aliquam finibus. Vestibulum lorem nulla, dictum ac libero non, mattis dictum nisl. Aenean semper lorem turpis. Praesent pellentesque ligula est, viverra molestie leo imperdiet ut. Nam vitae hendrerit justo. Nullam tincidunt et nibh ac volutpat. Aliquam vulputate mi aliquam fermentum rhoncus."),3)
- pa.add(Image(Img("kotlin.png")),1)
- pa.add(dock,2,alignSelf = FLEXALIGNITEMS.FLEXSTART)
- dock.width = 400 to UNIT.px
+ pa.add(Label("Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce nec fringilla turpis, vel molestie dolor. Vestibulum ut ex eget orci porta gravida eu sit amet tortor. Suspendisse vel fermentum purus, vel ornare tellus. Vivamus dictum, risus non viverra venenatis, magna mi pharetra purus, nec dignissim risus tortor a sem. Donec tincidunt dui ut eros laoreet consectetur. Nam dapibus vestibulum sem, eget accumsan ex vestibulum ac. Curabitur ac mi sit amet eros sodales dictum. Sed at felis at nunc aliquam finibus. Vestibulum lorem nulla, dictum ac libero non, mattis dictum nisl. Aenean semper lorem turpis. Praesent pellentesque ligula est, viverra molestie leo imperdiet ut. Nam vitae hendrerit justo. Nullam tincidunt et nibh ac volutpat. Aliquam vulputate mi aliquam fermentum rhoncus."), 3)
+ pa.add(Image(Img("kotlin.png")), 1)
+ pa.add(dock, 2, alignSelf = FLEXALIGNITEMS.FLEXSTART)
+ dock.width = 400.px()
root.add(pa)
val modal = Modal("Test okienka")
diff --git a/src/main/kotlin/pl/treksoft/kvision/core/StyledComponent.kt b/src/main/kotlin/pl/treksoft/kvision/core/StyledComponent.kt
new file mode 100644
index 00000000..5dea72ef
--- /dev/null
+++ b/src/main/kotlin/pl/treksoft/kvision/core/StyledComponent.kt
@@ -0,0 +1,198 @@
+package pl.treksoft.kvision.core
+
+import pl.treksoft.kvision.css.Border
+import pl.treksoft.kvision.css.CssSize
+import pl.treksoft.kvision.snabbdom.StringPair
+
+abstract class StyledComponent : KVObject {
+
+ var width: CssSize? = null
+ set(value) {
+ field = value
+ refresh()
+ }
+ var minWidth: CssSize? = null
+ set(value) {
+ field = value
+ refresh()
+ }
+ var maxWidth: CssSize? = null
+ set(value) {
+ field = value
+ refresh()
+ }
+ var height: CssSize? = null
+ set(value) {
+ field = value
+ refresh()
+ }
+ var minHeight: CssSize? = null
+ set(value) {
+ field = value
+ refresh()
+ }
+ var maxHeight: CssSize? = null
+ set(value) {
+ field = value
+ refresh()
+ }
+ var border: Border? = null
+ set(value) {
+ field = value
+ refresh()
+ }
+ var borderTop: Border? = null
+ set(value) {
+ field = value
+ refresh()
+ }
+ var borderRight: Border? = null
+ set(value) {
+ field = value
+ refresh()
+ }
+ var borderBottom: Border? = null
+ set(value) {
+ field = value
+ refresh()
+ }
+ var borderLeft: Border? = null
+ set(value) {
+ field = value
+ refresh()
+ }
+ var margin: CssSize? = null
+ set(value) {
+ field = value
+ refresh()
+ }
+ var marginTop: CssSize? = null
+ set(value) {
+ field = value
+ refresh()
+ }
+ var marginRight: CssSize? = null
+ set(value) {
+ field = value
+ refresh()
+ }
+ var marginBottom: CssSize? = null
+ set(value) {
+ field = value
+ refresh()
+ }
+ var marginLeft: CssSize? = null
+ set(value) {
+ field = value
+ refresh()
+ }
+ var padding: CssSize? = null
+ set(value) {
+ field = value
+ refresh()
+ }
+ var paddingTop: CssSize? = null
+ set(value) {
+ field = value
+ refresh()
+ }
+ var paddingRight: CssSize? = null
+ set(value) {
+ field = value
+ refresh()
+ }
+ var paddingBottom: CssSize? = null
+ set(value) {
+ field = value
+ refresh()
+ }
+ var paddingLeft: CssSize? = null
+ set(value) {
+ field = value
+ refresh()
+ }
+
+ private var snStyleCache: List<StringPair>? = null
+
+ protected open fun refresh(): StyledComponent {
+ snStyleCache = null
+ return this
+ }
+
+ protected fun getSnStyleInternal(): List<StringPair> {
+ return snStyleCache ?: {
+ val s = getSnStyle()
+ snStyleCache = s
+ s
+ }()
+ }
+
+ @Suppress("ComplexMethod")
+ protected open fun getSnStyle(): List<StringPair> {
+ val snstyle = mutableListOf<StringPair>()
+ width?.let {
+ snstyle.add("width" to it.first.toString() + it.second.unit)
+ }
+ minWidth?.let {
+ snstyle.add("min-width" to it.first.toString() + it.second.unit)
+ }
+ maxWidth?.let {
+ snstyle.add("max-width" to it.first.toString() + it.second.unit)
+ }
+ height?.let {
+ snstyle.add("height" to it.first.toString() + it.second.unit)
+ }
+ minHeight?.let {
+ snstyle.add("min-height" to it.first.toString() + it.second.unit)
+ }
+ maxHeight?.let {
+ snstyle.add("max-height" to it.first.toString() + it.second.unit)
+ }
+ border?.let {
+ snstyle.add("border" to it.asString())
+ }
+ borderTop?.let {
+ snstyle.add("border-top" to it.asString())
+ }
+ borderRight?.let {
+ snstyle.add("border-right" to it.asString())
+ }
+ borderBottom?.let {
+ snstyle.add("border-bottom" to it.asString())
+ }
+ borderLeft?.let {
+ snstyle.add("border-left" to it.asString())
+ }
+ margin?.let {
+ snstyle.add("margin" to it.first.toString() + it.second.unit)
+ }
+ marginTop?.let {
+ snstyle.add("margin-top" to it.first.toString() + it.second.unit)
+ }
+ marginRight?.let {
+ snstyle.add("margin-right" to it.first.toString() + it.second.unit)
+ }
+ marginBottom?.let {
+ snstyle.add("margin-bottom" to it.first.toString() + it.second.unit)
+ }
+ marginLeft?.let {
+ snstyle.add("margin-left" to it.first.toString() + it.second.unit)
+ }
+ padding?.let {
+ snstyle.add("padding" to it.first.toString() + it.second.unit)
+ }
+ paddingTop?.let {
+ snstyle.add("padding-top" to it.first.toString() + it.second.unit)
+ }
+ paddingRight?.let {
+ snstyle.add("padding-right" to it.first.toString() + it.second.unit)
+ }
+ paddingBottom?.let {
+ snstyle.add("padding-bottom" to it.first.toString() + it.second.unit)
+ }
+ paddingLeft?.let {
+ snstyle.add("padding-left" to it.first.toString() + it.second.unit)
+ }
+ return snstyle
+ }
+}
diff --git a/src/main/kotlin/pl/treksoft/kvision/core/Types.kt b/src/main/kotlin/pl/treksoft/kvision/core/Types.kt
deleted file mode 100644
index df0eb98b..00000000
--- a/src/main/kotlin/pl/treksoft/kvision/core/Types.kt
+++ /dev/null
@@ -1,21 +0,0 @@
-package pl.treksoft.kvision.core
-
-@Suppress("EnumNaming", "EnumEntryName")
-enum class UNIT(val unit: String) {
- px("px"),
- pt("pt"),
- em("em"),
- cm("cm"),
- mm("mm"),
- `in`("in"),
- pc("pc"),
- ch("ch"),
- rem("rem"),
- vw("vw"),
- vh("vh"),
- vmin("vmin"),
- vmax("vmax"),
- perc("%")
-}
-
-typealias Length = Pair<Int, UNIT>
diff --git a/src/main/kotlin/pl/treksoft/kvision/core/Widget.kt b/src/main/kotlin/pl/treksoft/kvision/core/Widget.kt
index ff34186b..d56e7614 100644
--- a/src/main/kotlin/pl/treksoft/kvision/core/Widget.kt
+++ b/src/main/kotlin/pl/treksoft/kvision/core/Widget.kt
@@ -18,7 +18,7 @@ import pl.treksoft.kvision.snabbdom.snOpt
import pl.treksoft.kvision.snabbdom.snStyle
@Suppress("TooManyFunctions")
-open class Widget(classes: Set<String> = setOf()) : KVObject {
+open class Widget(classes: Set<String> = setOf()) : StyledComponent() {
val classes = classes.toMutableSet()
val listeners = mutableListOf<SnOn<Widget>.() -> Unit>()
@@ -47,21 +47,10 @@ open class Widget(classes: Set<String> = setOf()) : KVObject {
field = value
refresh()
}
- var width: Length? = null
- set(value) {
- field = value
- refresh()
- }
- var height: Length? = null
- set(value) {
- field = value
- refresh()
- }
private var vnode: VNode? = null
private var snAttrsCache: List<StringPair>? = null
- private var snStyleCache: List<StringPair>? = null
private var snClassCache: List<StringBoolPair>? = null
private var snOnCache: com.github.snabbdom.On? = null
private var snHooksCache: com.github.snabbdom.Hooks? = null
@@ -100,14 +89,6 @@ open class Widget(classes: Set<String> = setOf()) : KVObject {
}()
}
- private fun getSnStyleInternal(): List<StringPair> {
- return snStyleCache ?: {
- val s = getSnStyle()
- snStyleCache = s
- s
- }()
- }
-
private fun getSnClassInternal(): List<StringBoolPair> {
return snClassCache ?: {
val s = getSnClass()
@@ -132,22 +113,10 @@ open class Widget(classes: Set<String> = setOf()) : KVObject {
}()
}
- protected open fun getSnStyle(): List<StringPair> {
- val snstyle = mutableListOf<StringPair>()
- width?.let {
- snstyle.add("width" to it.first.toString() + it.second.unit)
- }
- height?.let {
- snstyle.add("height" to it.first.toString() + it.second.unit)
- }
- return snstyle
- }
-
protected open fun getSnClass(): List<StringBoolPair> {
return classes.map { c -> c to true } + if (visible) listOf() else listOf("hidden" to true)
}
-
protected open fun getSnAttrs(): List<StringPair> {
val snattrs = mutableListOf<StringPair>()
id?.let {
@@ -249,9 +218,9 @@ open class Widget(classes: Set<String> = setOf()) : KVObject {
return this
}
- protected fun refresh(): Widget {
+ override fun refresh(): Widget {
+ super.refresh()
snAttrsCache = null
- snStyleCache = null
snClassCache = null
snOnCache = null
snHooksCache = null
diff --git a/src/main/kotlin/pl/treksoft/kvision/css/Css.kt b/src/main/kotlin/pl/treksoft/kvision/css/Css.kt
new file mode 100644
index 00000000..14c242e8
--- /dev/null
+++ b/src/main/kotlin/pl/treksoft/kvision/css/Css.kt
@@ -0,0 +1,62 @@
+package pl.treksoft.kvision.css
+
+import pl.treksoft.kvision.utils.Utils
+
+@Suppress("EnumNaming", "EnumEntryName")
+enum class UNIT(val unit: String) {
+ px("px"),
+ pt("pt"),
+ em("em"),
+ cm("cm"),
+ mm("mm"),
+ `in`("in"),
+ pc("pc"),
+ ch("ch"),
+ rem("rem"),
+ vw("vw"),
+ vh("vh"),
+ vmin("vmin"),
+ vmax("vmax"),
+ perc("%")
+}
+
+typealias CssSize = Pair<Int, UNIT>
+
+enum class BORDERSTYLE(val borderStyle: String) {
+ NONE("none"),
+ HIDDEN("hidden"),
+ DOTTED("dotted"),
+ DASHED("dashed"),
+ SOLID("solid"),
+ DOUBLE("double"),
+ GROOVE("groove"),
+ RIDGE("ridge"),
+ INSET("inset"),
+ OUTSET("outset"),
+ INITIAL("initial"),
+ INHERIT("inherit")
+}
+
+enum class COLOR(val color: String) {
+ RED("red"),
+ BLUE("blue"),
+ GREEN("green"),
+ BLACK("black"),
+ WHITE("white")
+}
+
+class Border private constructor(private val width: CssSize? = null, private val style: BORDERSTYLE? = null,
+ private val color: String? = null) {
+ constructor(width: CssSize? = null, style: BORDERSTYLE? = null) : this(width, style, null)
+ constructor(width: CssSize? = null, style: BORDERSTYLE? = null, color: Int) : this(width, style,
+ "#" + Utils.intToHexString(color))
+
+ constructor(width: CssSize? = null, style: BORDERSTYLE? = null, color: COLOR) : this(width, style, color.color)
+
+ fun asString(): String {
+ val w = width?.let {
+ it.first.toString() + it.second.unit
+ }
+ return w.orEmpty() + " " + style?.borderStyle.orEmpty() + " " + color.orEmpty()
+ }
+}
diff --git a/src/main/kotlin/pl/treksoft/kvision/panel/SplitPanel.kt b/src/main/kotlin/pl/treksoft/kvision/panel/SplitPanel.kt
index 06f9be59..9084742a 100644
--- a/src/main/kotlin/pl/treksoft/kvision/panel/SplitPanel.kt
+++ b/src/main/kotlin/pl/treksoft/kvision/panel/SplitPanel.kt
@@ -4,7 +4,7 @@ import com.github.snabbdom.VNode
import pl.treksoft.jquery.JQuery
import pl.treksoft.jquery.JQueryEventObject
import pl.treksoft.kvision.core.Container
-import pl.treksoft.kvision.core.UNIT
+import pl.treksoft.kvision.css.UNIT
import pl.treksoft.kvision.html.TAG
import pl.treksoft.kvision.html.Tag
import pl.treksoft.kvision.snabbdom.obj
diff --git a/src/main/kotlin/pl/treksoft/kvision/utils/Utils.kt b/src/main/kotlin/pl/treksoft/kvision/utils/Utils.kt
new file mode 100644
index 00000000..5a9bf5a6
--- /dev/null
+++ b/src/main/kotlin/pl/treksoft/kvision/utils/Utils.kt
@@ -0,0 +1,38 @@
+@file:Suppress("TooManyFunctions")
+package pl.treksoft.kvision.utils
+
+import pl.treksoft.kvision.css.CssSize
+import pl.treksoft.kvision.css.UNIT
+
+fun Int.px(): CssSize = Pair(this, UNIT.px)
+fun Int.em(): CssSize = Pair(this, UNIT.em)
+fun Int.pt(): CssSize = Pair(this, UNIT.pt)
+fun Int.perc(): CssSize = Pair(this, UNIT.perc)
+fun Int.rem(): CssSize = Pair(this, UNIT.rem)
+fun Int.ch(): CssSize = Pair(this, UNIT.ch)
+fun Int.cm(): CssSize = Pair(this, UNIT.cm)
+fun Int.mm(): CssSize = Pair(this, UNIT.mm)
+@Suppress("FunctionNaming")
+fun Int.`in`(): CssSize = Pair(this, UNIT.`in`)
+fun Int.pc(): CssSize = Pair(this, UNIT.pc)
+fun Int.vh(): CssSize = Pair(this, UNIT.vh)
+fun Int.vw(): CssSize = Pair(this, UNIT.vw)
+fun Int.vmin(): CssSize = Pair(this, UNIT.vmin)
+fun Int.vmax(): CssSize = Pair(this, UNIT.vmax)
+
+object Utils {
+
+ private val hex = arrayOf("0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f")
+
+ @Suppress("MagicNumber")
+ fun intToHexString(n: Int): String {
+ var result = ""
+ var num = n
+ for (i in 0 until 6) {
+ result = hex[num and 0xF] + result
+ num = num shr 4
+ }
+ return result
+ }
+
+}