diff options
Diffstat (limited to 'src/main/kotlin')
19 files changed, 804 insertions, 21 deletions
diff --git a/src/main/kotlin/pl/treksoft/kvision/Application.kt b/src/main/kotlin/pl/treksoft/kvision/ApplicationBase.kt index a7b3d465..a7b3d465 100644 --- a/src/main/kotlin/pl/treksoft/kvision/Application.kt +++ b/src/main/kotlin/pl/treksoft/kvision/ApplicationBase.kt diff --git a/src/main/kotlin/pl/treksoft/kvision/main.kt b/src/main/kotlin/pl/treksoft/kvision/Main.kt index 01ce118f..918cd51f 100644 --- a/src/main/kotlin/pl/treksoft/kvision/main.kt +++ b/src/main/kotlin/pl/treksoft/kvision/Main.kt @@ -26,15 +26,10 @@ fun main(args: Array<String>) { } fun start(state: dynamic): ApplicationBase? { - if (document.body?.hasClass("kvision") ?: false) { - val application = MainApplication() - - @Suppress("UnsafeCastFromDynamic") - application.start(state?.appState ?: emptyMap()) - - return application - } else { - return null - } + if (document.getElementById("showcase") == null) return null + val application = Showcase() + @Suppress("UnsafeCastFromDynamic") + application.start(state?.appState ?: emptyMap()) + return application } diff --git a/src/main/kotlin/pl/treksoft/kvision/MainApplication.kt b/src/main/kotlin/pl/treksoft/kvision/MainApplication.kt deleted file mode 100644 index 92bcca53..00000000 --- a/src/main/kotlin/pl/treksoft/kvision/MainApplication.kt +++ /dev/null @@ -1,11 +0,0 @@ -package pl.treksoft.kvision - -import kotlin.browser.* - -class MainApplication : ApplicationBase() { - - override fun start(state: Map<String, Any>) { - } - - override fun dispose() = mapOf<String, Any>() -}
\ No newline at end of file diff --git a/src/main/kotlin/pl/treksoft/kvision/Showcase.kt b/src/main/kotlin/pl/treksoft/kvision/Showcase.kt new file mode 100644 index 00000000..caa66269 --- /dev/null +++ b/src/main/kotlin/pl/treksoft/kvision/Showcase.kt @@ -0,0 +1,102 @@ +package pl.treksoft.kvision + +import pl.treksoft.kvision.basic.Label +import pl.treksoft.kvision.core.Container +import pl.treksoft.kvision.core.Img +import pl.treksoft.kvision.core.KVManager +import pl.treksoft.kvision.core.Root +import pl.treksoft.kvision.dropdown.DropDown +import pl.treksoft.kvision.html.* +import pl.treksoft.kvision.html.TAG.H1 +import pl.treksoft.kvision.routing.routing + +class Showcase : ApplicationBase() { + + override fun start(state: Map<String, Any>) { + val root = Root("showcase") + val container = Container(setOf("abc", "def")) + val h1 = Tag(H1, "To jest <i>test pisania</i> tekstu", false, ALIGN.NONE, classes = setOf("test", "test2")) + container.add(h1) + val label = Label("KVLabel1") + container.add(label) + val label2 = Label("KVLabel2") + container.add(label2) + root.add(container) + label.hide() + label.show() + + val dd = DropDown("Dropdown", listOf("DAsdasd asdasdas das", "dasdasd asdasdas das"), "flag") + root.add(dd) + + val p = Tag(TAG.P, "To jest prawo", align = ALIGN.RIGHT) + p.title = "Tytuł" + root.add(p) + val del = InTag(INTAG.DEL, "To jest deleted") + root.add(del) + + val list = ListTag(LIST.DL_HORIZ, listOf("abc", "de<b>fdasdasdasddasd</b>tdasdas", "Dasdsada", "dasdasdads"), true) + root.add(list) + + val img = Image(Img("kotlin.png"), "Image", true, IMAGE_SHAPE.ROUNDED) + root.add(img) + + val button = Button("To jest przycisk FA", "fa-flag", BUTTON_STYLE.DANGER) + button.setEventListener<Button> { + click = { _ -> println(self.text) } + } + root.add(button) + val button2 = Button("To jest przycisk", "flag", BUTTON_STYLE.DANGER) + button2.setEventListener { + click = { e -> + println("2" + e) + button.setEventListener { + click = null + } + } + } + root.add(button2) + val button3 = Button("To jest przycisk IMG", image = Img("kotlin.png")) + button3.setEventListener { + click = { e -> + println("3" + e) + button.setEventListener<Button> { + click = { _ -> println(self.text) } + dblclick = { e -> println("111" + e) } + } + } + } + root.add(button3) + + println("init routing") + routing.on({ -> println("root") }) + .on("/abc", { -> println("abc") }) + .on("/test", { -> println("test") }) + .resolve() + +// routing.on(RegExp("/abc/def/(.*)/(.*)/(.*)"), { x,y,z,u,v -> println(x) }) + +// router.on("/test", { -> println("test") }) + +/* val vnode = h("div", snOpt { + on = snEvents { + click = { e -> println(e) } + } + }, arrayOf( + h("span", snOpt { + style = snStyle("fontWeight" to "bold", "fontStyle" to "italic") + }, arrayOf("This is bold")), + " and this is just normal text ", + h("a", snOpt { + props = snProps("href" to "/foo", "target" to "_blank") + }, "I\'ll take you places!") + )) + val v = patch(container, vnode) + val vnode2 = virtualize("<a href='/top' target='_top'>Test2</a>") + patch(v, vnode2)*/ + } + + override fun dispose(): Map<String, Any> { + KVManager.shutdown() + return mapOf<String, Any>() + } +}
\ No newline at end of file diff --git a/src/main/kotlin/pl/treksoft/kvision/basic/Label.kt b/src/main/kotlin/pl/treksoft/kvision/basic/Label.kt new file mode 100644 index 00000000..c0aa5ad2 --- /dev/null +++ b/src/main/kotlin/pl/treksoft/kvision/basic/Label.kt @@ -0,0 +1,7 @@ +package pl.treksoft.kvision.basic + +import pl.treksoft.kvision.html.InTag +import pl.treksoft.kvision.html.INTAG + +open class Label(text: String, rich: Boolean = false) : InTag(INTAG.SPAN, text, rich) { +}
\ No newline at end of file diff --git a/src/main/kotlin/pl/treksoft/kvision/core/Container.kt b/src/main/kotlin/pl/treksoft/kvision/core/Container.kt new file mode 100644 index 00000000..575fa73b --- /dev/null +++ b/src/main/kotlin/pl/treksoft/kvision/core/Container.kt @@ -0,0 +1,32 @@ +package pl.treksoft.kvision.core + +import com.github.snabbdom.VNode + +open class Container(classes: Set<String> = setOf()) : Widget(classes) { + private val children: MutableList<Widget> = mutableListOf() + + override fun render(): VNode { + return kvh("div", childrenVNodes()) + } + + protected open fun childrenVNodes(): Array<VNode> { + return children.filter { it.visible }.map { it.render() }.toTypedArray() + } + + open fun add(child: Widget) { + children.add(child) + child.parent = this + refresh() + } + + open fun remove(child: Widget) { + children.remove(child) + child.clearParent() + refresh() + } + + open fun removeAt(index: Int) { + children.removeAt(index).clearParent() + refresh() + } +}
\ No newline at end of file diff --git a/src/main/kotlin/pl/treksoft/kvision/core/Img.kt b/src/main/kotlin/pl/treksoft/kvision/core/Img.kt new file mode 100644 index 00000000..08063a4a --- /dev/null +++ b/src/main/kotlin/pl/treksoft/kvision/core/Img.kt @@ -0,0 +1,10 @@ +package pl.treksoft.kvision.core + +typealias ResString = String + +object Img { + operator fun invoke(src: ResString) = at(src) + + @Suppress("UnsafeCastFromDynamic", "NOTHING_TO_INLINE") + private inline fun at(src: ResString): String = pl.treksoft.kvision.require("./img/" + src) +} diff --git a/src/main/kotlin/pl/treksoft/kvision/core/KVManager.kt b/src/main/kotlin/pl/treksoft/kvision/core/KVManager.kt new file mode 100644 index 00000000..97f0fd62 --- /dev/null +++ b/src/main/kotlin/pl/treksoft/kvision/core/KVManager.kt @@ -0,0 +1,34 @@ +package pl.treksoft.kvision.core + +import com.github.snabbdom.* +import pl.treksoft.kvision.require +import pl.treksoft.kvision.routing.routing +import kotlin.browser.document +import kotlin.dom.clear + +object KVManager { + private val bootstrap_webpack = require("bootstrap-webpack") + private val font_awesome_webpack = require("font-awesome-webpack") + + private val sdPatch = Snabbdom.init(arrayOf(classModule, attributesModule, propsModule, styleModule, eventListenersModule, datasetModule)) + private val sdVirtualize = require("snabbdom-virtualize/strings").default + + internal fun patch(id: String, vnode: VNode): VNode { + val container = document.getElementById(id) + container?.clear() + return sdPatch(container, vnode) + } + + internal fun patch(oldVNode: VNode, newVNode: VNode): VNode { + return sdPatch(oldVNode, newVNode) + } + + @Suppress("UnsafeCastFromDynamic") + internal fun virtualize(html: String): VNode { + return sdVirtualize(html) + } + + fun shutdown() { + routing.destroy() + } +}
\ No newline at end of file diff --git a/src/main/kotlin/pl/treksoft/kvision/core/KVObject.kt b/src/main/kotlin/pl/treksoft/kvision/core/KVObject.kt new file mode 100644 index 00000000..aa90ccf8 --- /dev/null +++ b/src/main/kotlin/pl/treksoft/kvision/core/KVObject.kt @@ -0,0 +1,3 @@ +package pl.treksoft.kvision.core + +interface KVObject diff --git a/src/main/kotlin/pl/treksoft/kvision/core/Root.kt b/src/main/kotlin/pl/treksoft/kvision/core/Root.kt new file mode 100644 index 00000000..b5911c36 --- /dev/null +++ b/src/main/kotlin/pl/treksoft/kvision/core/Root.kt @@ -0,0 +1,27 @@ +package pl.treksoft.kvision.core + +import com.github.snabbdom.VNode +import pl.treksoft.kvision.snabbdom.StringBoolPair + +class Root(id: String, private val fluid: Boolean = false) : Container() { + private var vnode: VNode = render() + + init { + vnode = KVManager.patch(id, this.render()) + this.id = id + } + + override fun render(): VNode { + return kvh("div#" + id, childrenVNodes()) + } + + override fun getSnClass(): List<StringBoolPair> { + val css = if (fluid) "container-fluid" else "container" + return super.getSnClass() + (css to true) + } + + override fun refresh() { + vnode = KVManager.patch(vnode, render()) + } + +}
\ No newline at end of file diff --git a/src/main/kotlin/pl/treksoft/kvision/core/Widget.kt b/src/main/kotlin/pl/treksoft/kvision/core/Widget.kt new file mode 100644 index 00000000..8da8b0b6 --- /dev/null +++ b/src/main/kotlin/pl/treksoft/kvision/core/Widget.kt @@ -0,0 +1,121 @@ +package pl.treksoft.kvision.core + +import com.github.snabbdom.On +import com.github.snabbdom.VNode +import com.github.snabbdom.VNodeData +import com.github.snabbdom.h +import pl.treksoft.kvision.snabbdom.* + +open class Widget(classes: Set<String> = setOf()) : KVObject { + + val classes = classes.toMutableSet() + val listeners = mutableListOf<SnOn<Widget>.() -> Unit>() + + var parent: Widget? = null + internal set + + var visible: Boolean = true + set(value) { + field = value + refresh() + } + var title: String? = null + set(value) { + field = value + refresh() + } + var id: String? = null + set(value) { + field = value + refresh() + } + + internal open fun render(): VNode { + return kvh("div") + } + + protected open fun kvh(s: String): VNode { + return h(s, getSnOpt()) + } + + protected open fun kvh(s: String, children: Array<dynamic>): VNode { + return h(s, getSnOpt(), children) + } + + protected open fun getSnOpt(): VNodeData { + return snOpt { + attrs = snAttrs(* getSnAttrs().toTypedArray()) + style = snStyle(* getSnStyle().toTypedArray()) + `class` = snClasses(* getSnClass().toTypedArray()) + on = getSnOn() + } + } + + protected open fun getSnStyle(): List<StringPair> { + return listOf() + } + + 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>() + if (id != null) { + snattrs.add("id" to id.orEmpty()) + } + if (title != null) { + snattrs.add("title" to title.orEmpty()) + } + return snattrs + } + + protected open fun getSnOn(): On { + val handlers = On(this) + listeners.forEach { on -> (handlers::apply)(on) } + return handlers + } + + @Suppress("UNCHECKED_CAST") + open fun <T : Widget> setEventListener(block: SnOn<T>.() -> Unit) { + listeners.add(block as SnOn<Widget>.() -> Unit) + refresh() + } + + open fun setEventListener(block: SnOn<Widget>.() -> Unit) { + listeners.add(block) + refresh() + } + + open fun removeEventListeners() { + listeners.clear() + refresh() + } + + open fun show() { + visible = true + } + + open fun hide() { + visible = false + } + + open fun addCssClass(css: String) { + this.classes.add(css) + refresh() + } + + open fun removeCssClass(css: String) { + this.classes.remove(css) + refresh() + } + + internal fun clearParent() { + this.parent = null + } + + protected open fun refresh() { + this.parent?.refresh() + } +}
\ No newline at end of file diff --git a/src/main/kotlin/pl/treksoft/kvision/dropdown/DropDown.kt b/src/main/kotlin/pl/treksoft/kvision/dropdown/DropDown.kt new file mode 100644 index 00000000..eef229e4 --- /dev/null +++ b/src/main/kotlin/pl/treksoft/kvision/dropdown/DropDown.kt @@ -0,0 +1,55 @@ +package pl.treksoft.kvision.dropdown + +import com.github.snabbdom.VNode +import com.github.snabbdom.h +import pl.treksoft.kvision.core.Container +import pl.treksoft.kvision.core.KVManager +import pl.treksoft.kvision.core.ResString +import pl.treksoft.kvision.html.* +import pl.treksoft.kvision.snabbdom.StringPair + +open class DropDown(text: String, elements: List<String>, icon: String? = null, style: BUTTON_STYLE = BUTTON_STYLE.DEFAULT, size: BUTTON_SIZE? = null, + block: Boolean = false, disabled: Boolean = false, image: ResString? = null, classes: Set<String> = setOf()) : Container(classes) { + val idk = "abc" + val button: DropDownButton = DropDownButton(idk, text, icon, style, size, block, disabled, image, setOf("dropdown")) + val list: DropDownListTag = DropDownListTag(idk, elements, setOf("dropdown-menu")) + + init { + this.addCssClass("dropdown") + this.add(button) + this.add(list) + } +} + +open class DropDownButton(id: String, text: String, icon: String? = null, style: BUTTON_STYLE = BUTTON_STYLE.DEFAULT, size: BUTTON_SIZE? = null, + block: Boolean = false, disabled: Boolean = false, image: ResString? = null, classes: Set<String> = setOf()) : + Button(text, icon, style, size, block, disabled, image, classes) { + + init { + this.id = id + } + + override fun getSnAttrs(): List<StringPair> { + return super.getSnAttrs() + listOf("data-toggle" to "dropdown", "aria-haspopup" to "true", "aria-expanded" to "false") + } +} + +open class DropDownListTag(val ariaId: String, elements: List<String>, classes: Set<String> = setOf()) : ListTag(LIST.UL, elements, true, classes) { + + override fun render(): VNode { + val children = elements.map { el -> element("li", el, true) }.toTypedArray() + return kvh(type.tagName, children) + } + + private fun element(name: String, value: String, rich: Boolean): VNode { + if (rich) { + return h(name, arrayOf(KVManager.virtualize("<a href='#'>$value</a>"))) + } else { + return h(name, value) + } + } + + override fun getSnAttrs(): List<StringPair> { + return super.getSnAttrs() + listOf("aria-labelledby" to ariaId) + } +}
\ No newline at end of file diff --git a/src/main/kotlin/pl/treksoft/kvision/html/Button.kt b/src/main/kotlin/pl/treksoft/kvision/html/Button.kt new file mode 100644 index 00000000..81df4eaf --- /dev/null +++ b/src/main/kotlin/pl/treksoft/kvision/html/Button.kt @@ -0,0 +1,99 @@ +package pl.treksoft.kvision.html + +import com.github.snabbdom.VNode +import pl.treksoft.kvision.core.KVManager +import pl.treksoft.kvision.core.ResString +import pl.treksoft.kvision.core.Widget +import pl.treksoft.kvision.snabbdom.StringBoolPair +import pl.treksoft.kvision.snabbdom.StringPair + +enum class BUTTON_STYLE(val className: String) { + DEFAULT("btn-default"), + PRIMARY("btn-primary"), + SUCCESS("btn-success"), + INFO("btn-info"), + WARNING("btn-warning"), + DANGER("btn-danger"), + LINK("btn-link") +} + +enum class BUTTON_SIZE(val className: String) { + LARGE("btn-lg"), + SMALL("btn-sm"), + XSMALL("btn-xs") +} + +open class Button(text: String, icon: String? = null, style: BUTTON_STYLE = BUTTON_STYLE.DEFAULT, size: BUTTON_SIZE? = null, + block: Boolean = false, disabled: Boolean = false, image: ResString? = null, classes: Set<String> = setOf()) : Widget(classes) { + var text = text + set(value) { + field = value + refresh() + } + var icon = icon + set(value) { + field = value + refresh() + } + var style = style + set(value) { + field = value + refresh() + } + var size = size + set(value) { + field = value + refresh() + } + var block = block + set(value) { + field = value + refresh() + } + var disabled = disabled + set(value) { + field = value + refresh() + } + var image = image + set(value) { + field = value + refresh() + } + + override fun render(): VNode { + val t = if (icon != null) { + if (icon?.startsWith("fa-") == true) { + arrayOf(KVManager.virtualize("<i class='fa $icon fa-lg'></i>"), " " + text) + } else { + arrayOf(KVManager.virtualize("<span class='glyphicon glyphicon-$icon'></span>"), " " + text) + } + } else if (image != null) { + arrayOf(KVManager.virtualize("<img src='$image' alt='' />"), " " + text) + } else { + arrayOf(text) + } + return kvh("button", t) + } + + override fun getSnClass(): List<StringBoolPair> { + val cl = super.getSnClass().toMutableList() + cl.add("btn" to true) + cl.add(style.className to true) + if (size != null) { + cl.add(size?.className.orEmpty() to true) + } + if (block) { + cl.add("btn-block" to true) + } + if (disabled) { + cl.add("disabled" to true) + } + return cl + } + + override fun getSnAttrs(): List<StringPair> { + return super.getSnAttrs() + ("type" to "button") + } + +}
\ No newline at end of file diff --git a/src/main/kotlin/pl/treksoft/kvision/html/Image.kt b/src/main/kotlin/pl/treksoft/kvision/html/Image.kt new file mode 100644 index 00000000..3e9fe5d6 --- /dev/null +++ b/src/main/kotlin/pl/treksoft/kvision/html/Image.kt @@ -0,0 +1,66 @@ +package pl.treksoft.kvision.html + +import com.github.snabbdom.VNode +import pl.treksoft.kvision.core.ResString +import pl.treksoft.kvision.core.Widget +import pl.treksoft.kvision.snabbdom.StringBoolPair +import pl.treksoft.kvision.snabbdom.StringPair + +enum class IMAGE_SHAPE(val className: String) { + ROUNDED("img-rounded"), + CIRCLE("img-circle"), + THUMBNAIL("img-thumbnail") +} + +open class Image(src: ResString, alt: String? = null, responsive: Boolean = false, shape: IMAGE_SHAPE? = null, centered: Boolean = false, classes: Set<String> = setOf()) : Widget(classes) { + var src = src + set(value) { + field = value + refresh() + } + var alt = alt + set(value) { + field = value + refresh() + } + var responsive = responsive + set(value) { + field = value + refresh() + } + var shape = shape + set(value) { + field = value + refresh() + } + var centered = centered + set(value) { + field = value + refresh() + } + + override fun render(): VNode { + return kvh("img") + } + + override fun getSnAttrs(): List<StringPair> { + val pr = super.getSnAttrs().toMutableList() + pr.add("src" to src) + if (alt != null) pr.add("alt" to alt.orEmpty()) + return pr + } + + override fun getSnClass(): List<StringBoolPair> { + val cl = super.getSnClass().toMutableList() + if (responsive) { + cl.add("img-responsive" to true) + } + if (centered) { + cl.add("center-block" to true) + } + if (shape != null) { + cl.add(shape?.className.orEmpty() to true) + } + return cl + } +}
\ No newline at end of file diff --git a/src/main/kotlin/pl/treksoft/kvision/html/InTag.kt b/src/main/kotlin/pl/treksoft/kvision/html/InTag.kt new file mode 100644 index 00000000..88f69435 --- /dev/null +++ b/src/main/kotlin/pl/treksoft/kvision/html/InTag.kt @@ -0,0 +1,48 @@ +package pl.treksoft.kvision.html + +import com.github.snabbdom.VNode +import pl.treksoft.kvision.core.KVManager +import pl.treksoft.kvision.core.Widget + +enum class INTAG(val tagName: String) { + MARK("mark"), + DEL("del"), + S("s"), + INS("ins"), + U("u"), + SMALL("small"), + STRONG("strong"), + EM("em"), + CITE("cite"), + CODE("code"), + KBD("kbd"), + VAR("var"), + SAMP("samp"), + SPAN("span") +} + +open class InTag(type: INTAG, text: String, rich: Boolean = false, classes: Set<String> = setOf()) : Widget(classes) { + var type = type + set(value) { + field = value + refresh() + } + var text = text + set(value) { + field = value + refresh() + } + var rich = rich + set(value) { + field = value + refresh() + } + + override fun render(): VNode { + if (rich) { + return kvh(type.tagName, arrayOf(KVManager.virtualize("<span>$text</span>"))) + } else { + return kvh(type.tagName, arrayOf(text)) + } + } +}
\ No newline at end of file diff --git a/src/main/kotlin/pl/treksoft/kvision/html/List.kt b/src/main/kotlin/pl/treksoft/kvision/html/List.kt new file mode 100644 index 00000000..918f1576 --- /dev/null +++ b/src/main/kotlin/pl/treksoft/kvision/html/List.kt @@ -0,0 +1,62 @@ +package pl.treksoft.kvision.html + +import com.github.snabbdom.VNode +import com.github.snabbdom.h +import pl.treksoft.kvision.core.KVManager +import pl.treksoft.kvision.core.Widget +import pl.treksoft.kvision.snabbdom.StringBoolPair + +enum class LIST(val tagName: String) { + UL("ul"), + OL("ol"), + UNSTYLED("ul"), + INLINE("ul"), + DL("dl"), + DL_HORIZ("dl") +} + +open class ListTag(type: LIST, elements: List<String>, rich: Boolean = false, classes: Set<String> = setOf()) : Widget(classes) { + var type = type + set(value) { + field = value + refresh() + } + var elements = elements + set(value) { + field = value + refresh() + } + var rich = rich + set(value) { + field = value + refresh() + } + + override fun render(): VNode { + val children = when (type) { + LIST.UL, LIST.OL, LIST.UNSTYLED, LIST.INLINE -> elements.map { el -> element("li", el, rich) } + LIST.DL, LIST.DL_HORIZ -> elements.mapIndexed { index, el -> element(if (index % 2 == 0) "dt" else "dd", el, rich) } + }.toTypedArray() + return kvh(type.tagName, children) + } + + private fun element(name: String, value: String, rich: Boolean): VNode { + if (rich) { + return h(name, arrayOf(KVManager.virtualize("<span>$value</span>"))) + } else { + return h(name, value) + } + } + + override fun getSnClass(): List<StringBoolPair> { + val cl = super.getSnClass().toMutableList() + if (type == LIST.UNSTYLED) { + cl.add("list-unstyled" to true) + } else if (type == LIST.INLINE) { + cl.add("list-inline" to true) + } else if (type == LIST.DL_HORIZ) { + cl.add("dl-horizontal" to true) + } + return cl + } +}
\ No newline at end of file diff --git a/src/main/kotlin/pl/treksoft/kvision/html/Tag.kt b/src/main/kotlin/pl/treksoft/kvision/html/Tag.kt new file mode 100644 index 00000000..60910707 --- /dev/null +++ b/src/main/kotlin/pl/treksoft/kvision/html/Tag.kt @@ -0,0 +1,69 @@ +package pl.treksoft.kvision.html + +import com.github.snabbdom.VNode +import pl.treksoft.kvision.core.KVManager +import pl.treksoft.kvision.core.Widget +import pl.treksoft.kvision.snabbdom.StringBoolPair + +enum class TAG(val tagName: String) { + H1("h1"), + H2("h2"), + H3("h3"), + H4("h4"), + H5("h5"), + H6("h6"), + P("p"), + ABBR("abbr"), + ADDRESS("address"), + BLOCKQUOTE("blockquote"), + FOOTER("footer"), + PRE("pre") +} + +enum class ALIGN(val className: String) { + NONE(""), + LEFT("text-left"), + CENTER("text-center"), + RIGHT("text-right"), + JUSTIFY("text-justify"), + NOWRAP("text-nowrap") +} + +open class Tag(type: TAG, text: String, rich: Boolean = false, align: ALIGN = ALIGN.NONE, classes: Set<String> = setOf()) : Widget(classes) { + var type = type + set(value) { + field = value + refresh() + } + var text = text + set(value) { + field = value + refresh() + } + var rich = rich + set(value) { + field = value + refresh() + } + var align = align + set(value) { + field = value + refresh() + } + + override fun render(): VNode { + if (rich) { + return kvh(type.tagName, arrayOf(KVManager.virtualize("<span>$text</span>"))) + } else { + return kvh(type.tagName, arrayOf(text)) + } + } + + override fun getSnClass(): List<StringBoolPair> { + val cl = super.getSnClass().toMutableList() + if (align != ALIGN.NONE) { + cl.add(align.className to true) + } + return cl + } +}
\ No newline at end of file diff --git a/src/main/kotlin/pl/treksoft/kvision/routing/Routing.kt b/src/main/kotlin/pl/treksoft/kvision/routing/Routing.kt new file mode 100644 index 00000000..709f966c --- /dev/null +++ b/src/main/kotlin/pl/treksoft/kvision/routing/Routing.kt @@ -0,0 +1,7 @@ +package pl.treksoft.kvision.routing + +import pl.treksoft.navigo.Navigo + +open class Routing : Navigo(null, true, "#!") + +val routing = Routing() diff --git a/src/main/kotlin/pl/treksoft/kvision/snabbdom/Types.kt b/src/main/kotlin/pl/treksoft/kvision/snabbdom/Types.kt new file mode 100644 index 00000000..789417e6 --- /dev/null +++ b/src/main/kotlin/pl/treksoft/kvision/snabbdom/Types.kt @@ -0,0 +1,57 @@ +package pl.treksoft.kvision.snabbdom + +import com.github.snabbdom.* +import pl.treksoft.kvision.core.Widget + +external class Object + +fun obj(init: dynamic.() -> Unit): dynamic { + return (Object()).apply(init) +} + +@Suppress("UnsafeCastFromDynamic") +private fun VNodeData(): VNodeData = js("({})") + +interface SnOn<T> : On { + var self: T +} + +fun snOpt(block: VNodeData.() -> Unit) = (VNodeData()::apply)(block) + +@Suppress("UnsafeCastFromDynamic") +internal fun On(widget: Widget): SnOn<Widget> { + val obj = js("({})") + obj["self"] = widget + return obj +} + +typealias StringPair = Pair<String, String> +typealias StringBoolPair = Pair<String, Boolean> + +@Suppress("UnsafeCastFromDynamic") +fun snStyle(vararg pairs: StringPair): VNodeStyle { + return obj { + pairs.forEach { (key, value) -> this[key] = value } + } +} + +@Suppress("UnsafeCastFromDynamic") +fun snProps(vararg pairs: StringPair): Props { + return obj { + pairs.forEach { (key, value) -> this[key] = value } + } +} + +@Suppress("UnsafeCastFromDynamic") +fun snClasses(vararg pairs: StringBoolPair): Classes { + return obj { + pairs.forEach { (key, value) -> this[key] = value } + } +} + +@Suppress("UnsafeCastFromDynamic") +fun snAttrs(vararg pairs: StringPair): Attrs { + return obj { + pairs.forEach { (key, value) -> this[key] = value } + } +} |