Release 0.1.5, add css styles

This commit is contained in:
2019-05-28 13:36:32 +02:00
parent ff5684a376
commit 2b1f3fa5a4
4 changed files with 82 additions and 59 deletions

View File

@@ -1,5 +1,5 @@
group 'nl.astraeus' group 'nl.astraeus'
version '0.1.5-SNAPSHOT' version '0.1.6-SNAPSHOT'
apply plugin: 'kotlin2js' apply plugin: 'kotlin2js'
apply plugin: 'kotlin-dce-js' apply plugin: 'kotlin-dce-js'

View File

@@ -34,9 +34,9 @@
<output-test url="file://$MODULE_DIR$/out/test/classes" /> <output-test url="file://$MODULE_DIR$/out/test/classes" />
<exclude-output /> <exclude-output />
<content url="file://$MODULE_DIR$"> <content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src/main/kotlin" type="kotlin-source" /> <sourceFolder url="file://$MODULE_DIR$/src/main/kotlin" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/test/kotlin" type="kotlin-test" /> <sourceFolder url="file://$MODULE_DIR$/src/test/kotlin" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="kotlin-resource" /> <sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
<excludeFolder url="file://$MODULE_DIR$/.gradle" /> <excludeFolder url="file://$MODULE_DIR$/.gradle" />
<excludeFolder url="file://$MODULE_DIR$/build" /> <excludeFolder url="file://$MODULE_DIR$/build" />
<excludeFolder url="file://$MODULE_DIR$/out" /> <excludeFolder url="file://$MODULE_DIR$/out" />

View File

@@ -4,6 +4,7 @@ import kotlinx.html.Entities
import kotlinx.html.Tag import kotlinx.html.Tag
import kotlinx.html.TagConsumer import kotlinx.html.TagConsumer
import kotlinx.html.Unsafe import kotlinx.html.Unsafe
import org.w3c.dom.HTMLElement
import org.w3c.dom.Node import org.w3c.dom.Node
import org.w3c.dom.events.Event import org.w3c.dom.events.Event
import org.w3c.dom.get import org.w3c.dom.get
@@ -25,20 +26,16 @@ enum class ElementType {
class KompElement( class KompElement(
val type: ElementType, val type: ElementType,
val komponent: Komponent?, val komponent: Komponent,
var text: String, var text: String,
var attributes: MutableMap<String, String>? = null, var attributes: MutableMap<String, String>? = null,
val children: MutableList<KompElement>? = null, val children: MutableList<KompElement>? = null,
val events: MutableMap<String, (Event) -> Unit>? = null val events: MutableMap<String, (Event) -> Unit>? = null
) { ) {
constructor(text: String, type: ElementType) : this( constructor(komponent: Komponent, text: String, type: ElementType) : this(
type, type,
if (type == ElementType.KOMPONENT) { komponent,
throw IllegalStateException("Type KOMPONENT not allowed in String constructor")
} else {
null
},
text, text,
if (type == ElementType.TAG) { if (type == ElementType.TAG) {
HashMap() HashMap()
@@ -68,7 +65,7 @@ class KompElement(
/* shallow equals check */ /* shallow equals check */
fun equals(other: KompElement): Boolean { fun equals(other: KompElement): Boolean {
if (komponent != null) { if (other.isKomponent() && isKomponent()) {
val result = komponent == other.komponent val result = komponent == other.komponent
if (!result && Komponent.logEquals) { if (!result && Komponent.logEquals) {
console.log("!= komponent", this, other) console.log("!= komponent", this, other)
@@ -129,10 +126,6 @@ class KompElement(
ElementType.KOMPONENT -> { ElementType.KOMPONENT -> {
val komp = komponent val komp = komponent
if (komp == null) {
throw IllegalStateException("komponent == null in type Komponent!")
} else {
val kompElement = komp.create() val kompElement = komp.create()
val element = kompElement.create() val element = kompElement.create()
@@ -141,7 +134,6 @@ class KompElement(
element element
} }
}
ElementType.TEXT -> document.createTextNode(text) ElementType.TEXT -> document.createTextNode(text)
ElementType.UNSAFE -> { ElementType.UNSAFE -> {
val div = if (svg) { val div = if (svg) {
@@ -179,7 +171,34 @@ class KompElement(
} }
(attributes?.entries)?.forEach { entry -> (attributes?.entries)?.forEach { entry ->
if (entry.key == "class") {
val classes = entry.value.split(" ")
val classNames = StringBuilder()
for (cls in classes) {
val cssStyle = komponent?.declaredStyles?.get(cls)
if (cssStyle != null) {
if (result is HTMLElement) {
for (index in 0 until cssStyle.length) {
val propertyName = cssStyle.item(index)
result.style.setProperty(propertyName, cssStyle.getPropertyValue(propertyName))
}
}
} else {
classNames.append(cls)
classNames.append(" ")
}
}
if (result !is HTMLElement) {
result.setAttribute(entry.key, entry.value) result.setAttribute(entry.key, entry.value)
} else {
result.className = classNames.toString()
}
} else {
result.setAttribute(entry.key, entry.value)
}
} }
(events?.entries)?.forEach { event -> (events?.entries)?.forEach { event ->
@@ -262,7 +281,9 @@ class UnsafeWrapper: Unsafe {
} }
} }
class KompConsumer : TagConsumer<KompElement> { class KompConsumer(
val komponent: Komponent
) : TagConsumer<KompElement> {
val stack = ArrayList<KompElement>() val stack = ArrayList<KompElement>()
var currentTag: KompElement? = null var currentTag: KompElement? = null
@@ -280,7 +301,7 @@ class KompConsumer : TagConsumer<KompElement> {
override fun onTagContent(content: CharSequence) { override fun onTagContent(content: CharSequence) {
//console.log("KC.onTagContent", content) //console.log("KC.onTagContent", content)
currentTag?.children?.add(KompElement(content.toString(), ElementType.TEXT)) currentTag?.children?.add(KompElement(komponent, content.toString(), ElementType.TEXT))
} }
override fun onTagContentEntity(entity: Entities) { override fun onTagContentEntity(entity: Entities) {
@@ -294,7 +315,7 @@ class KompConsumer : TagConsumer<KompElement> {
block.invoke(txt) block.invoke(txt)
//console.log("KC.onTagContentUnsafe", txt) //console.log("KC.onTagContentUnsafe", txt)
currentTag?.children?.add(KompElement(txt.text, ElementType.UNSAFE)) currentTag?.children?.add(KompElement(komponent, txt.text, ElementType.UNSAFE))
} }
override fun onTagEnd(tag: Tag) { override fun onTagEnd(tag: Tag) {
@@ -326,7 +347,7 @@ class KompConsumer : TagConsumer<KompElement> {
stack.add(this) stack.add(this)
} }
currentTag = KompElement(tag.tagName, ElementType.TAG) currentTag = KompElement(komponent, tag.tagName, ElementType.TAG)
currentTag?.attributes = tag.attributes currentTag?.attributes = tag.attributes
} }

View File

@@ -1,8 +1,11 @@
package nl.astraeus.komp package nl.astraeus.komp
import kotlinx.html.HtmlBlockTag import kotlinx.html.HtmlBlockTag
import org.w3c.dom.HTMLDivElement
import org.w3c.dom.HTMLElement import org.w3c.dom.HTMLElement
import org.w3c.dom.Node import org.w3c.dom.Node
import org.w3c.dom.css.CSSStyleDeclaration
import kotlin.browser.document
fun HtmlBlockTag.include(component: Komponent) { fun HtmlBlockTag.include(component: Komponent) {
val consumer = this.consumer val consumer = this.consumer
@@ -19,18 +22,23 @@ enum class UpdateStrategy {
abstract class Komponent { abstract class Komponent {
var element: Node? = null var element: Node? = null
var kompElement: KompElement? = null var kompElement: KompElement? = null
var rendered = false val declaredStyles: MutableMap<String, CSSStyleDeclaration> = HashMap()
open fun create(): KompElement { open fun create(): KompElement {
val result = render(KompConsumer()) val result = render(KompConsumer(this))
return result return result
} }
abstract fun render(consumer: KompConsumer): KompElement abstract fun render(consumer: KompConsumer): KompElement
open fun refresh(forceRefresh: Boolean = false) { open fun declareStyle(className: String, block: CSSStyleDeclaration.() -> Unit) {
if (!rendered || forceRefresh) { val style = (document.createElement("div") as HTMLDivElement).style
block(style)
declaredStyles[className] = style
}
open fun refresh() {
element?.let { element -> element?.let { element ->
if (logRenderEvent) { if (logRenderEvent) {
console.log("Rendering", this) console.log("Rendering", this)
@@ -52,15 +60,11 @@ abstract class Komponent {
kompElement = newElement kompElement = newElement
this.element = replacedElement this.element = replacedElement
rendered = true
}
} else {
update()
} }
} }
open fun update() { open fun update() {
refresh(true) refresh()
} }
override fun equals(other: Any?): Boolean { override fun equals(other: Any?): Boolean {
@@ -70,14 +74,12 @@ abstract class Komponent {
other as Komponent other as Komponent
if (kompElement != other.kompElement) return false if (kompElement != other.kompElement) return false
if (rendered != other.rendered) return false
return true return true
} }
override fun hashCode(): Int { override fun hashCode(): Int {
var result = kompElement?.hashCode() ?: 0 var result = kompElement?.hashCode() ?: 0
result = 31 * result + rendered.hashCode()
return result return result
} }
@@ -91,7 +93,7 @@ abstract class Komponent {
fun replaceNode(newKomponent: KompElement, oldElement: Node): Node { fun replaceNode(newKomponent: KompElement, oldElement: Node): Node {
val newElement = newKomponent.create() val newElement = newKomponent.create()
if (Komponent.logReplaceEvent) { if (logReplaceEvent) {
console.log("Replace", oldElement, newElement) console.log("Replace", oldElement, newElement)
} }
@@ -110,7 +112,7 @@ abstract class Komponent {
fun removeElement(element: Node) { fun removeElement(element: Node) {
val parent = element.parentElement ?: throw IllegalArgumentException("Element has no parent!?") val parent = element.parentElement ?: throw IllegalArgumentException("Element has no parent!?")
if (Komponent.logReplaceEvent) { if (logReplaceEvent) {
console.log("Remove", element) console.log("Remove", element)
} }