aboutsummaryrefslogtreecommitdiff
path: root/src/main
diff options
context:
space:
mode:
Diffstat (limited to 'src/main')
-rw-r--r--src/main/kotlin/pl/treksoft/kvision/core/Widget.kt2
-rw-r--r--src/main/kotlin/pl/treksoft/kvision/form/check/CheckBox.kt15
-rw-r--r--src/main/kotlin/pl/treksoft/kvision/form/check/CheckInput.kt24
-rw-r--r--src/main/kotlin/pl/treksoft/kvision/form/check/Radio.kt9
-rw-r--r--src/main/kotlin/pl/treksoft/kvision/form/check/RadioGroup.kt19
-rw-r--r--src/main/kotlin/pl/treksoft/kvision/form/check/RadioGroupInput.kt17
-rw-r--r--src/main/kotlin/pl/treksoft/kvision/form/range/Range.kt9
-rw-r--r--src/main/kotlin/pl/treksoft/kvision/form/range/RangeInput.kt17
-rw-r--r--src/main/kotlin/pl/treksoft/kvision/form/select/SimpleSelect.kt9
-rw-r--r--src/main/kotlin/pl/treksoft/kvision/form/select/SimpleSelectInput.kt17
-rw-r--r--src/main/kotlin/pl/treksoft/kvision/form/text/AbstractText.kt10
-rw-r--r--src/main/kotlin/pl/treksoft/kvision/form/text/AbstractTextInput.kt26
-rw-r--r--src/main/kotlin/pl/treksoft/kvision/state/StateBinding.kt2
13 files changed, 157 insertions, 19 deletions
diff --git a/src/main/kotlin/pl/treksoft/kvision/core/Widget.kt b/src/main/kotlin/pl/treksoft/kvision/core/Widget.kt
index ba4db0cc..b28943dd 100644
--- a/src/main/kotlin/pl/treksoft/kvision/core/Widget.kt
+++ b/src/main/kotlin/pl/treksoft/kvision/core/Widget.kt
@@ -1017,7 +1017,7 @@ open class Widget(classes: Set<String> = setOf()) : StyledComponent(), Component
* An extension function which binds the widget to the observable state.
* Used by [pl.treksoft.kvision.state.bind]
*/
- internal fun <S : Any, W : Widget> W.bindState(
+ internal fun <S, W : Widget> W.bindState(
observableState: ObservableState<S>,
factory: (W.(S) -> Unit)
): W {
diff --git a/src/main/kotlin/pl/treksoft/kvision/form/check/CheckBox.kt b/src/main/kotlin/pl/treksoft/kvision/form/check/CheckBox.kt
index 60147114..370f5ab1 100644
--- a/src/main/kotlin/pl/treksoft/kvision/form/check/CheckBox.kt
+++ b/src/main/kotlin/pl/treksoft/kvision/form/check/CheckBox.kt
@@ -30,6 +30,7 @@ import pl.treksoft.kvision.form.FieldLabel
import pl.treksoft.kvision.form.FormHorizontalRatio
import pl.treksoft.kvision.form.InvalidFeedback
import pl.treksoft.kvision.panel.SimplePanel
+import pl.treksoft.kvision.state.ObservableState
import pl.treksoft.kvision.utils.SnOn
/**
@@ -55,7 +56,7 @@ enum class CheckBoxStyle(internal val className: String) {
open class CheckBox(
value: Boolean = false, name: String? = null, label: String? = null,
rich: Boolean = false
-) : SimplePanel(setOf("form-check", "abc-checkbox")), BoolFormControl {
+) : SimplePanel(setOf("form-check", "abc-checkbox")), BoolFormControl, ObservableState<Boolean> {
/**
* The selection state of the checkbox.
@@ -65,6 +66,7 @@ open class CheckBox(
set(value) {
input.value = value
}
+
/**
* The value attribute of the generated HTML input element.
*
@@ -76,6 +78,7 @@ open class CheckBox(
set(value) {
input.startValue = value
}
+
/**
* The label text bound to the input element.
*/
@@ -84,6 +87,7 @@ open class CheckBox(
set(value) {
flabel.content = value
}
+
/**
* Determines if [label] can contain HTML code.
*/
@@ -92,14 +96,17 @@ open class CheckBox(
set(value) {
flabel.rich = value
}
+
/**
* The style (one of Bootstrap standard colors) of the input.
*/
var style: CheckBoxStyle? by refreshOnUpdate()
+
/**
* Determines if the checkbox is rendered as a circle.
*/
var circled by refreshOnUpdate(false)
+
/**
* Determines if the checkbox is rendered inline.
*/
@@ -189,6 +196,12 @@ open class CheckBox(
addCssClass("form-group")
}
+ override fun getState(): Boolean = input.getState()
+
+ override fun subscribe(observer: (Boolean) -> Unit): () -> Unit {
+ return input.subscribe(observer)
+ }
+
companion object {
internal var counter = 0
}
diff --git a/src/main/kotlin/pl/treksoft/kvision/form/check/CheckInput.kt b/src/main/kotlin/pl/treksoft/kvision/form/check/CheckInput.kt
index f93fd436..70d57c51 100644
--- a/src/main/kotlin/pl/treksoft/kvision/form/check/CheckInput.kt
+++ b/src/main/kotlin/pl/treksoft/kvision/form/check/CheckInput.kt
@@ -29,6 +29,7 @@ import pl.treksoft.kvision.core.Widget
import pl.treksoft.kvision.form.FormInput
import pl.treksoft.kvision.form.InputSize
import pl.treksoft.kvision.form.ValidationStatus
+import pl.treksoft.kvision.state.ObservableState
/**
* Type of the check input control (checkbox or radio).
@@ -49,7 +50,9 @@ enum class CheckInputType(internal val type: String) {
abstract class CheckInput(
type: CheckInputType = CheckInputType.CHECKBOX, value: Boolean = false,
classes: Set<String> = setOf()
-) : Widget(classes), FormInput {
+) : Widget(classes), FormInput, ObservableState<Boolean> {
+
+ protected val observers = mutableListOf<(Boolean) -> Unit>()
init {
this.setInternalEventListener<CheckInput> {
@@ -67,7 +70,8 @@ abstract class CheckInput(
/**
* The selection state of the input.
*/
- var value by refreshOnUpdate(value) { refreshState() }
+ var value by refreshOnUpdate(value) { refreshState(); observers.forEach { ob -> ob(it) } }
+
/**
* The value attribute of the generated HTML input element.
*
@@ -75,26 +79,32 @@ abstract class CheckInput(
* bound to the input selection state.
*/
var startValue by refreshOnUpdate(value) { this.value = it; refresh() }
+
/**
* The type of the generated HTML input element.
*/
var type by refreshOnUpdate(type)
+
/**
* The name attribute of the generated HTML input element.
*/
override var name: String? by refreshOnUpdate()
+
/**
* Determines if the field is disabled.
*/
override var disabled by refreshOnUpdate(false)
+
/**
* The additional String value used for the radio button group.
*/
var extraValue: String? by refreshOnUpdate()
+
/**
* The size of the input.
*/
override var size: InputSize? by refreshOnUpdate()
+
/**
* The validation status of the input.
*/
@@ -169,4 +179,14 @@ abstract class CheckInput(
override fun blur() {
getElementJQuery()?.blur()
}
+
+ override fun getState(): Boolean = value
+
+ override fun subscribe(observer: (Boolean) -> Unit): () -> Unit {
+ observers += observer
+ observer(value)
+ return {
+ observers -= observer
+ }
+ }
}
diff --git a/src/main/kotlin/pl/treksoft/kvision/form/check/Radio.kt b/src/main/kotlin/pl/treksoft/kvision/form/check/Radio.kt
index b8757da2..03ae8595 100644
--- a/src/main/kotlin/pl/treksoft/kvision/form/check/Radio.kt
+++ b/src/main/kotlin/pl/treksoft/kvision/form/check/Radio.kt
@@ -30,6 +30,7 @@ import pl.treksoft.kvision.form.FieldLabel
import pl.treksoft.kvision.form.FormHorizontalRatio
import pl.treksoft.kvision.form.InvalidFeedback
import pl.treksoft.kvision.panel.SimplePanel
+import pl.treksoft.kvision.state.ObservableState
import pl.treksoft.kvision.utils.SnOn
/**
@@ -56,7 +57,7 @@ enum class RadioStyle(internal val className: String) {
open class Radio(
value: Boolean = false, extraValue: String? = null, name: String? = null, label: String? = null,
rich: Boolean = false
-) : SimplePanel(classes = setOf("form-check")), BoolFormControl {
+) : SimplePanel(classes = setOf("form-check")), BoolFormControl, ObservableState<Boolean> {
/**
* The selection state of the radio button.
@@ -204,6 +205,12 @@ open class Radio(
addCssClass("form-group")
}
+ override fun getState(): Boolean = input.getState()
+
+ override fun subscribe(observer: (Boolean) -> Unit): () -> Unit {
+ return input.subscribe(observer)
+ }
+
companion object {
internal var counter = 0
}
diff --git a/src/main/kotlin/pl/treksoft/kvision/form/check/RadioGroup.kt b/src/main/kotlin/pl/treksoft/kvision/form/check/RadioGroup.kt
index 234f5327..6433d708 100644
--- a/src/main/kotlin/pl/treksoft/kvision/form/check/RadioGroup.kt
+++ b/src/main/kotlin/pl/treksoft/kvision/form/check/RadioGroup.kt
@@ -31,6 +31,7 @@ import pl.treksoft.kvision.form.InvalidFeedback
import pl.treksoft.kvision.form.StringFormControl
import pl.treksoft.kvision.form.ValidationStatus
import pl.treksoft.kvision.panel.SimplePanel
+import pl.treksoft.kvision.state.ObservableState
/**
* The form field component rendered as a group of HTML *input type="radio"* elements with the same name attribute.
@@ -51,7 +52,9 @@ open class RadioGroup(
options: List<StringPair>? = null, value: String? = null, name: String? = null, inline: Boolean = false,
label: String? = null,
rich: Boolean = false
-) : SimplePanel(setOf("form-group")), StringFormControl {
+) : SimplePanel(setOf("form-group")), StringFormControl, ObservableState<String?> {
+
+ protected val observers = mutableListOf<(String?) -> Unit>()
/**
* A list of options (label to value pairs) for the group.
@@ -61,7 +64,7 @@ open class RadioGroup(
/**
* A value of the selected option.
*/
- override var value by refreshOnUpdate(value) { setValueToChildren(it) }
+ override var value by refreshOnUpdate(value) { setValueToChildren(it); observers.forEach { ob -> ob(it) } }
/**
* Determines if the options are rendered inline.
@@ -73,6 +76,7 @@ open class RadioGroup(
set(value) {
setDisabledToChildren(value)
}
+
/**
* The label text of the options group.
*/
@@ -81,6 +85,7 @@ open class RadioGroup(
set(value) {
flabel.content = value
}
+
/**
* Determines if [label] can contain HTML code.
*/
@@ -226,6 +231,16 @@ open class RadioGroup(
invalidFeedback.addCssClass("col-sm-${horizontalRatio.fields}")
}
+ override fun getState(): String? = value
+
+ override fun subscribe(observer: (String?) -> Unit): () -> Unit {
+ observers += observer
+ observer(value)
+ return {
+ observers -= observer
+ }
+ }
+
companion object {
internal var counter = 0
}
diff --git a/src/main/kotlin/pl/treksoft/kvision/form/check/RadioGroupInput.kt b/src/main/kotlin/pl/treksoft/kvision/form/check/RadioGroupInput.kt
index 5a47c3ce..3e9f0def 100644
--- a/src/main/kotlin/pl/treksoft/kvision/form/check/RadioGroupInput.kt
+++ b/src/main/kotlin/pl/treksoft/kvision/form/check/RadioGroupInput.kt
@@ -28,6 +28,7 @@ import pl.treksoft.kvision.form.FormInput
import pl.treksoft.kvision.form.InputSize
import pl.treksoft.kvision.form.ValidationStatus
import pl.treksoft.kvision.panel.SimplePanel
+import pl.treksoft.kvision.state.ObservableState
/**
* The input component rendered as a group of HTML *input type="radio"* elements with the same name attribute.
@@ -44,7 +45,9 @@ import pl.treksoft.kvision.panel.SimplePanel
@Suppress("TooManyFunctions")
open class RadioGroupInput(
options: List<StringPair>? = null, value: String? = null, name: String? = null, inline: Boolean = false
-) : SimplePanel(setOf("form-group")), FormInput {
+) : SimplePanel(setOf("form-group")), FormInput, ObservableState<String?> {
+
+ protected val observers = mutableListOf<(String?) -> Unit>()
/**
* A list of options (label to value pairs) for the group.
@@ -54,7 +57,7 @@ open class RadioGroupInput(
/**
* A value of the selected option.
*/
- var value by refreshOnUpdate(value) { setValueToChildren(it) }
+ var value by refreshOnUpdate(value) { setValueToChildren(it); observers.forEach { ob -> ob(it) } }
/**
* Determines if the options are rendered inline.
@@ -172,6 +175,16 @@ open class RadioGroupInput(
getChildren().filterIsInstance<Radio>().firstOrNull()?.blur()
}
+ override fun getState(): String? = value
+
+ override fun subscribe(observer: (String?) -> Unit): () -> Unit {
+ observers += observer
+ observer(value)
+ return {
+ observers -= observer
+ }
+ }
+
companion object {
internal var counter = 0
}
diff --git a/src/main/kotlin/pl/treksoft/kvision/form/range/Range.kt b/src/main/kotlin/pl/treksoft/kvision/form/range/Range.kt
index dc8e57a0..d5acae8b 100644
--- a/src/main/kotlin/pl/treksoft/kvision/form/range/Range.kt
+++ b/src/main/kotlin/pl/treksoft/kvision/form/range/Range.kt
@@ -29,6 +29,7 @@ import pl.treksoft.kvision.form.FormHorizontalRatio
import pl.treksoft.kvision.form.InvalidFeedback
import pl.treksoft.kvision.form.NumberFormControl
import pl.treksoft.kvision.panel.SimplePanel
+import pl.treksoft.kvision.state.ObservableState
import pl.treksoft.kvision.utils.SnOn
/**
@@ -46,7 +47,7 @@ import pl.treksoft.kvision.utils.SnOn
open class Range(
value: Number? = null, name: String? = null, min: Number = 0, max: Number = 100, step: Number = DEFAULT_STEP,
label: String? = null, rich: Boolean = false
-) : SimplePanel(setOf("form-group")), NumberFormControl {
+) : SimplePanel(setOf("form-group")), NumberFormControl, ObservableState<Number?> {
/**
* Range input value.
@@ -212,6 +213,12 @@ open class Range(
invalidFeedback.addCssClass("col-sm-${horizontalRatio.fields}")
}
+ override fun getState(): Number? = input.getState()
+
+ override fun subscribe(observer: (Number?) -> Unit): () -> Unit {
+ return input.subscribe(observer)
+ }
+
companion object {
internal var counter = 0
}
diff --git a/src/main/kotlin/pl/treksoft/kvision/form/range/RangeInput.kt b/src/main/kotlin/pl/treksoft/kvision/form/range/RangeInput.kt
index 4649c654..6112022d 100644
--- a/src/main/kotlin/pl/treksoft/kvision/form/range/RangeInput.kt
+++ b/src/main/kotlin/pl/treksoft/kvision/form/range/RangeInput.kt
@@ -30,6 +30,7 @@ import pl.treksoft.kvision.core.Widget
import pl.treksoft.kvision.form.FormInput
import pl.treksoft.kvision.form.InputSize
import pl.treksoft.kvision.form.ValidationStatus
+import pl.treksoft.kvision.state.ObservableState
import pl.treksoft.kvision.utils.set
internal const val DEFAULT_STEP = 1
@@ -47,12 +48,14 @@ internal const val DEFAULT_STEP = 1
open class RangeInput(
value: Number? = null, min: Number = 0, max: Number = 100, step: Number = DEFAULT_STEP,
classes: Set<String> = setOf()
-) : Widget(classes + "form-control-range"), FormInput {
+) : Widget(classes + "form-control-range"), FormInput, ObservableState<Number?> {
+
+ protected val observers = mutableListOf<(Number?) -> Unit>()
/**
* Range input value.
*/
- var value by refreshOnUpdate(value ?: (min as Number?)) { refreshState() }
+ var value by refreshOnUpdate(value ?: (min as Number?)) { refreshState(); observers.forEach { ob -> ob(it) } }
/**
* The value attribute of the generated HTML input element.
@@ -223,6 +226,16 @@ open class RangeInput(
override fun blur() {
getElementJQuery()?.blur()
}
+
+ override fun getState(): Number? = value
+
+ override fun subscribe(observer: (Number?) -> Unit): () -> Unit {
+ observers += observer
+ observer(value)
+ return {
+ observers -= observer
+ }
+ }
}
/**
diff --git a/src/main/kotlin/pl/treksoft/kvision/form/select/SimpleSelect.kt b/src/main/kotlin/pl/treksoft/kvision/form/select/SimpleSelect.kt
index e797e050..043e8a02 100644
--- a/src/main/kotlin/pl/treksoft/kvision/form/select/SimpleSelect.kt
+++ b/src/main/kotlin/pl/treksoft/kvision/form/select/SimpleSelect.kt
@@ -30,6 +30,7 @@ import pl.treksoft.kvision.form.FieldLabel
import pl.treksoft.kvision.form.InvalidFeedback
import pl.treksoft.kvision.form.StringFormControl
import pl.treksoft.kvision.panel.SimplePanel
+import pl.treksoft.kvision.state.ObservableState
import pl.treksoft.kvision.utils.SnOn
/**
@@ -47,7 +48,7 @@ import pl.treksoft.kvision.utils.SnOn
open class SimpleSelect(
options: List<StringPair>? = null, value: String? = null, emptyOption: Boolean = false,
name: String? = null, label: String? = null, rich: Boolean = false
-) : SimplePanel(setOf("form-group")), StringFormControl {
+) : SimplePanel(setOf("form-group")), StringFormControl, ObservableState<String?> {
/**
* A list of options (value to label pairs) for the select control.
@@ -183,6 +184,12 @@ open class SimpleSelect(
input.blur()
}
+ override fun getState(): String? = input.getState()
+
+ override fun subscribe(observer: (String?) -> Unit): () -> Unit {
+ return input.subscribe(observer)
+ }
+
companion object {
internal var counter = 0
}
diff --git a/src/main/kotlin/pl/treksoft/kvision/form/select/SimpleSelectInput.kt b/src/main/kotlin/pl/treksoft/kvision/form/select/SimpleSelectInput.kt
index 63eb98b5..dd567cad 100644
--- a/src/main/kotlin/pl/treksoft/kvision/form/select/SimpleSelectInput.kt
+++ b/src/main/kotlin/pl/treksoft/kvision/form/select/SimpleSelectInput.kt
@@ -31,6 +31,7 @@ import pl.treksoft.kvision.form.ValidationStatus
import pl.treksoft.kvision.html.TAG
import pl.treksoft.kvision.html.Tag
import pl.treksoft.kvision.panel.SimplePanel
+import pl.treksoft.kvision.state.ObservableState
import pl.treksoft.kvision.utils.set
internal const val KVNULL = "#kvnull"
@@ -47,7 +48,9 @@ internal const val KVNULL = "#kvnull"
open class SimpleSelectInput(
options: List<StringPair>? = null, value: String? = null, emptyOption: Boolean = false,
classes: Set<String> = setOf()
-) : SimplePanel(classes + "form-control"), FormInput {
+) : SimplePanel(classes + "form-control"), FormInput, ObservableState<String?> {
+
+ protected val observers = mutableListOf<(String?) -> Unit>()
/**
* A list of options (value to label pairs) for the select control.
@@ -57,7 +60,7 @@ open class SimpleSelectInput(
/**
* Text input value.
*/
- var value by refreshOnUpdate(value) { refreshState() }
+ var value by refreshOnUpdate(value) { refreshState(); observers.forEach { ob -> ob(it) } }
/**
* The value of the selected child option.
@@ -207,6 +210,16 @@ open class SimpleSelectInput(
override fun blur() {
getElementJQuery()?.blur()
}
+
+ override fun getState(): String? = value
+
+ override fun subscribe(observer: (String?) -> Unit): () -> Unit {
+ observers += observer
+ observer(value)
+ return {
+ observers -= observer
+ }
+ }
}
/**
diff --git a/src/main/kotlin/pl/treksoft/kvision/form/text/AbstractText.kt b/src/main/kotlin/pl/treksoft/kvision/form/text/AbstractText.kt
index 8a5acf8b..9ac2a636 100644
--- a/src/main/kotlin/pl/treksoft/kvision/form/text/AbstractText.kt
+++ b/src/main/kotlin/pl/treksoft/kvision/form/text/AbstractText.kt
@@ -27,6 +27,7 @@ import pl.treksoft.kvision.form.FieldLabel
import pl.treksoft.kvision.form.InvalidFeedback
import pl.treksoft.kvision.form.StringFormControl
import pl.treksoft.kvision.panel.SimplePanel
+import pl.treksoft.kvision.state.ObservableState
import pl.treksoft.kvision.utils.SnOn
/**
@@ -37,7 +38,7 @@ import pl.treksoft.kvision.utils.SnOn
* @param rich determines if [label] can contain HTML code
*/
abstract class AbstractText(label: String? = null, rich: Boolean = false) :
- SimplePanel(setOf("form-group")), StringFormControl {
+ SimplePanel(setOf("form-group")), StringFormControl, ObservableState<String?> {
/**
* Text input value.
@@ -155,4 +156,11 @@ abstract class AbstractText(label: String? = null, rich: Boolean = false) :
override fun blur() {
input.blur()
}
+
+ override fun getState(): String? = input.getState()
+
+ override fun subscribe(observer: (String?) -> Unit): () -> Unit {
+ return input.subscribe(observer)
+ }
+
}
diff --git a/src/main/kotlin/pl/treksoft/kvision/form/text/AbstractTextInput.kt b/src/main/kotlin/pl/treksoft/kvision/form/text/AbstractTextInput.kt
index 192b33c8..98bd5f1a 100644
--- a/src/main/kotlin/pl/treksoft/kvision/form/text/AbstractTextInput.kt
+++ b/src/main/kotlin/pl/treksoft/kvision/form/text/AbstractTextInput.kt
@@ -28,6 +28,7 @@ import pl.treksoft.kvision.core.Widget
import pl.treksoft.kvision.form.FormInput
import pl.treksoft.kvision.form.InputSize
import pl.treksoft.kvision.form.ValidationStatus
+import pl.treksoft.kvision.state.ObservableState
/**
* Base class for basic text components.
@@ -39,7 +40,9 @@ import pl.treksoft.kvision.form.ValidationStatus
abstract class AbstractTextInput(
value: String? = null,
classes: Set<String> = setOf()
-) : Widget(classes), FormInput {
+) : Widget(classes), FormInput, ObservableState<String?> {
+
+ protected val observers = mutableListOf<(String?) -> Unit>()
init {
this.setInternalEventListener<AbstractTextInput> {
@@ -52,7 +55,8 @@ abstract class AbstractTextInput(
/**
* Text input value.
*/
- var value by refreshOnUpdate(value) { refreshState() }
+ var value by refreshOnUpdate(value) { refreshState(); observers.forEach { ob -> ob(it) } }
+
/**
* The value attribute of the generated HTML input element.
*
@@ -60,34 +64,42 @@ abstract class AbstractTextInput(
* bound to the text input value.
*/
var startValue by refreshOnUpdate(value) { this.value = it; refresh() }
+
/**
* The placeholder for the text input.
*/
var placeholder: String? by refreshOnUpdate()
+
/**
* The name attribute of the generated HTML input element.
*/
override var name: String? by refreshOnUpdate()
+
/**
* Maximal length of the text input value.
*/
var maxlength: Int? by refreshOnUpdate()
+
/**
* Determines if the field is disabled.
*/
override var disabled by refreshOnUpdate(false)
+
/**
* Determines if the text input is automatically focused.
*/
var autofocus: Boolean? by refreshOnUpdate()
+
/**
* Determines if the text input is read-only.
*/
var readonly: Boolean? by refreshOnUpdate()
+
/**
* The size of the input.
*/
override var size: InputSize? by refreshOnUpdate()
+
/**
* The validation status of the input.
*/
@@ -174,4 +186,14 @@ abstract class AbstractTextInput(
override fun blur() {
getElementJQuery()?.blur()
}
+
+ override fun getState(): String? = value
+
+ override fun subscribe(observer: (String?) -> Unit): () -> Unit {
+ observers += observer
+ observer(value)
+ return {
+ observers -= observer
+ }
+ }
}
diff --git a/src/main/kotlin/pl/treksoft/kvision/state/StateBinding.kt b/src/main/kotlin/pl/treksoft/kvision/state/StateBinding.kt
index d330f76d..6c8090b7 100644
--- a/src/main/kotlin/pl/treksoft/kvision/state/StateBinding.kt
+++ b/src/main/kotlin/pl/treksoft/kvision/state/StateBinding.kt
@@ -15,7 +15,7 @@ import pl.treksoft.kvision.core.Widget.Companion.bindState
* @param observableState the state
* @param factory a function which re-creates the view based on the given state
*/
-fun <S : Any, W : Widget> W.bind(
+fun <S, W : Widget> W.bind(
observableState: ObservableState<S>,
factory: (W.(S) -> Unit)
): W {