feat: use rescala by default for reactivity
downscale operations, supporting multiple reactive backends is too complex
This commit is contained in:
parent
07e4e4006a
commit
ec478533c3
11 changed files with 35 additions and 57 deletions
28
build.sbt
28
build.sbt
|
@ -36,7 +36,10 @@ lazy val dom = crossProject(JSPlatform, JVMPlatform)
|
||||||
.in(file("./dom"))
|
.in(file("./dom"))
|
||||||
.settings(
|
.settings(
|
||||||
name := "sfs-dom",
|
name := "sfs-dom",
|
||||||
version := "0.1.0-alpha"
|
version := "0.1.0-alpha",
|
||||||
|
libraryDependencies ++= Seq(
|
||||||
|
"de.tu-darmstadt.stg" %% "rescala" % "0.35.1"
|
||||||
|
)
|
||||||
)
|
)
|
||||||
.jvmSettings(
|
.jvmSettings(
|
||||||
libraryDependencies ++= Seq(
|
libraryDependencies ++= Seq(
|
||||||
|
@ -57,26 +60,3 @@ lazy val sfs = crossProject(JSPlatform, JVMPlatform)
|
||||||
version := "0.1.0-alpha"
|
version := "0.1.0-alpha"
|
||||||
)
|
)
|
||||||
.dependsOn(dom)
|
.dependsOn(dom)
|
||||||
|
|
||||||
lazy val sfsRouter = crossProject(JSPlatform, JVMPlatform)
|
|
||||||
.crossType(CrossType.Pure)
|
|
||||||
.in(file("./router"))
|
|
||||||
.settings(
|
|
||||||
name := "sfs-router",
|
|
||||||
version := "0.1.0-alpha"
|
|
||||||
)
|
|
||||||
|
|
||||||
lazy val sfsReScala = crossProject(JSPlatform, JVMPlatform)
|
|
||||||
.crossType(CrossType.Pure)
|
|
||||||
.in(file("./reactive/rescala"))
|
|
||||||
.settings(
|
|
||||||
name := "sfs-rescala",
|
|
||||||
version := "0.1.0-alpha"
|
|
||||||
)
|
|
||||||
|
|
||||||
lazy val sfsZio = project
|
|
||||||
.in(file("./integrations/zio"))
|
|
||||||
.settings(
|
|
||||||
name := "sfs-zio",
|
|
||||||
version := "0.1.0-alpha"
|
|
||||||
)
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package top.davidon.sfs.dom
|
package top.davidon.sfs.dom
|
||||||
|
|
||||||
|
import rescala.default.Signal
|
||||||
import top.davidon.sfs.dom.codecs.*
|
import top.davidon.sfs.dom.codecs.*
|
||||||
import top.davidon.sfs.dom.defs.attrs.{AriaAttrs, HtmlAttrs, SvgAttrs}
|
import top.davidon.sfs.dom.defs.attrs.{AriaAttrs, HtmlAttrs, SvgAttrs}
|
||||||
import top.davidon.sfs.dom.defs.complex.{ComplexHtmlKeys, ComplexSvgKeys}
|
import top.davidon.sfs.dom.defs.complex.{ComplexHtmlKeys, ComplexSvgKeys}
|
||||||
|
@ -7,6 +8,7 @@ import top.davidon.sfs.dom.defs.eventProps.GlobalEventProps
|
||||||
import top.davidon.sfs.dom.defs.props.HtmlProps
|
import top.davidon.sfs.dom.defs.props.HtmlProps
|
||||||
import top.davidon.sfs.dom.defs.tags.{HtmlTags, SvgTags}
|
import top.davidon.sfs.dom.defs.tags.{HtmlTags, SvgTags}
|
||||||
import top.davidon.sfs.dom.plain.PlainValue
|
import top.davidon.sfs.dom.plain.PlainValue
|
||||||
|
import top.davidon.sfs.dom.reactive.ReactiveValue
|
||||||
|
|
||||||
trait ScalaFullStackDOM
|
trait ScalaFullStackDOM
|
||||||
extends HtmlTags
|
extends HtmlTags
|
||||||
|
@ -42,4 +44,11 @@ trait ScalaFullStackDOM
|
||||||
def apply(from: Iterable[String]): PlainValue[Iterable[String], String] =
|
def apply(from: Iterable[String]): PlainValue[Iterable[String], String] =
|
||||||
PlainValue(from, IterableAsSpaceSeparatedStringCodec)
|
PlainValue(from, IterableAsSpaceSeparatedStringCodec)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
given signalToVal: Conversion[Signal[String], ReactiveValue[String, String]]
|
||||||
|
with {
|
||||||
|
def apply(from: Signal[String]): ReactiveValue[String, String] = {
|
||||||
|
ReactiveValue(from, StringAsIsCodec)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,9 @@
|
||||||
package top.davidon.sfs.dom.keys
|
package top.davidon.sfs.dom.keys
|
||||||
|
import rescala.default.Signal
|
||||||
import top.davidon.sfs.dom.codecs.Codec
|
import top.davidon.sfs.dom.codecs.Codec
|
||||||
import top.davidon.sfs.dom.mods.Modifier
|
import top.davidon.sfs.dom.mods.Modifier
|
||||||
import top.davidon.sfs.dom.plain.{PlainModifier, PlainValue}
|
import top.davidon.sfs.dom.plain.{PlainModifier, PlainValue}
|
||||||
import top.davidon.sfs.dom.reactive.{
|
import top.davidon.sfs.dom.reactive.{ReactiveModifier, ReactiveValue}
|
||||||
Observable,
|
|
||||||
ReactiveModifier,
|
|
||||||
ReactiveValue
|
|
||||||
}
|
|
||||||
|
|
||||||
class AriaAttr[V](
|
class AriaAttr[V](
|
||||||
suffix: String,
|
suffix: String,
|
||||||
|
@ -14,11 +11,11 @@ class AriaAttr[V](
|
||||||
) extends Key {
|
) extends Key {
|
||||||
override val name: String = "aria-" + suffix
|
override val name: String = "aria-" + suffix
|
||||||
|
|
||||||
@inline def apply(value: V | Observable[V]): Modifier[V, String] = {
|
@inline def apply(value: V | Signal[V]): Modifier[V, String] = {
|
||||||
this := value
|
this := value
|
||||||
}
|
}
|
||||||
|
|
||||||
def :=(value: V | Observable[V]): Modifier[V, String] = {
|
def :=(value: V | Signal[V]): Modifier[V, String] = {
|
||||||
Modifier.fromVorObservableV(this, value, codec)
|
Modifier.fromVorObservableV(this, value, codec)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,6 @@ import top.davidon.sfs.dom.Value
|
||||||
import top.davidon.sfs.dom.codecs.{EmptyCodec, StringAsIsCodec}
|
import top.davidon.sfs.dom.codecs.{EmptyCodec, StringAsIsCodec}
|
||||||
import top.davidon.sfs.dom.mods.{EventMod, Modifier}
|
import top.davidon.sfs.dom.mods.{EventMod, Modifier}
|
||||||
import top.davidon.sfs.dom.plain.{PlainModifier, PlainValue}
|
import top.davidon.sfs.dom.plain.{PlainModifier, PlainValue}
|
||||||
import top.davidon.sfs.dom.reactive.Observable
|
|
||||||
|
|
||||||
class EventProp[E <: dom.Event](override val name: String) extends Key {
|
class EventProp[E <: dom.Event](override val name: String) extends Key {
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
package top.davidon.sfs.dom.keys
|
package top.davidon.sfs.dom.keys
|
||||||
|
|
||||||
|
import rescala.default.Signal
|
||||||
import top.davidon.sfs.dom.codecs.Codec
|
import top.davidon.sfs.dom.codecs.Codec
|
||||||
import top.davidon.sfs.dom.Value
|
import top.davidon.sfs.dom.Value
|
||||||
import top.davidon.sfs.dom.mods.Modifier
|
import top.davidon.sfs.dom.mods.Modifier
|
||||||
import top.davidon.sfs.dom.plain.{PlainModifier, PlainValue}
|
import top.davidon.sfs.dom.plain.{PlainModifier, PlainValue}
|
||||||
import top.davidon.sfs.dom.reactive.{
|
import top.davidon.sfs.dom.reactive.{
|
||||||
Observable,
|
|
||||||
ReactiveModifier,
|
ReactiveModifier,
|
||||||
ReactiveValue
|
ReactiveValue
|
||||||
}
|
}
|
||||||
|
@ -14,11 +14,11 @@ class HtmlAttr[V](
|
||||||
override val name: String,
|
override val name: String,
|
||||||
val codec: Codec[V, String]
|
val codec: Codec[V, String]
|
||||||
) extends Key {
|
) extends Key {
|
||||||
@inline def apply(value: V | Observable[V]): Modifier[V, String] = {
|
@inline def apply(value: V | Signal[V]): Modifier[V, String] = {
|
||||||
this := value
|
this := value
|
||||||
}
|
}
|
||||||
|
|
||||||
def :=(value: V | Observable[V]): Modifier[V, String] = {
|
def :=(value: V | Signal[V]): Modifier[V, String] = {
|
||||||
Modifier.fromVorObservableV(this, value, codec)
|
Modifier.fromVorObservableV(this, value, codec)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,19 +1,19 @@
|
||||||
package top.davidon.sfs.dom.keys
|
package top.davidon.sfs.dom.keys
|
||||||
|
import rescala.default.Signal
|
||||||
import top.davidon.sfs.dom.codecs.Codec
|
import top.davidon.sfs.dom.codecs.Codec
|
||||||
import top.davidon.sfs.dom.Value
|
import top.davidon.sfs.dom.Value
|
||||||
import top.davidon.sfs.dom.mods.Modifier
|
import top.davidon.sfs.dom.mods.Modifier
|
||||||
import top.davidon.sfs.dom.plain.PlainValue
|
import top.davidon.sfs.dom.plain.PlainValue
|
||||||
import top.davidon.sfs.dom.reactive.Observable
|
|
||||||
|
|
||||||
class HtmlProp[V, DomV](
|
class HtmlProp[V, DomV](
|
||||||
override val name: String,
|
override val name: String,
|
||||||
val codec: Codec[V, DomV]
|
val codec: Codec[V, DomV]
|
||||||
) extends Key {
|
) extends Key {
|
||||||
@inline def apply(value: V | Observable[V]): Modifier[V, DomV] = {
|
@inline def apply(value: V | Signal[V]): Modifier[V, DomV] = {
|
||||||
this := value
|
this := value
|
||||||
}
|
}
|
||||||
|
|
||||||
def :=(value: V | Observable[V]): Modifier[V, DomV] = {
|
def :=(value: V | Signal[V]): Modifier[V, DomV] = {
|
||||||
Modifier.fromVorObservableV(this, value, codec)
|
Modifier.fromVorObservableV(this, value, codec)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package top.davidon.sfs.dom.keys
|
package top.davidon.sfs.dom.keys
|
||||||
|
import rescala.default.Signal
|
||||||
import top.davidon.sfs.dom.codecs.Codec
|
import top.davidon.sfs.dom.codecs.Codec
|
||||||
import top.davidon.sfs.dom.mods.Modifier
|
import top.davidon.sfs.dom.mods.Modifier
|
||||||
import top.davidon.sfs.dom.reactive.Observable
|
|
||||||
|
|
||||||
class SvgAttr[V](
|
class SvgAttr[V](
|
||||||
val localName: String,
|
val localName: String,
|
||||||
|
@ -13,11 +13,11 @@ class SvgAttr[V](
|
||||||
|
|
||||||
val namespaceUri: Option[String] = namespacePrefix.map(SvgAttr.namespaceUri)
|
val namespaceUri: Option[String] = namespacePrefix.map(SvgAttr.namespaceUri)
|
||||||
|
|
||||||
@inline def apply(value: V | Observable[V]): Modifier[V, String] = {
|
@inline def apply(value: V | Signal[V]): Modifier[V, String] = {
|
||||||
this := value
|
this := value
|
||||||
}
|
}
|
||||||
|
|
||||||
def :=(value: V | Observable[V]): Modifier[V, String] = {
|
def :=(value: V | Signal[V]): Modifier[V, String] = {
|
||||||
Modifier.fromVorObservableV(this, value, codec)
|
Modifier.fromVorObservableV(this, value, codec)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
package top.davidon.sfs.dom.mods
|
package top.davidon.sfs.dom.mods
|
||||||
|
|
||||||
|
import rescala.default.Signal
|
||||||
import top.davidon.sfs.dom.Value
|
import top.davidon.sfs.dom.Value
|
||||||
import top.davidon.sfs.dom.codecs.Codec
|
import top.davidon.sfs.dom.codecs.Codec
|
||||||
import top.davidon.sfs.dom.keys.Key
|
import top.davidon.sfs.dom.keys.Key
|
||||||
import top.davidon.sfs.dom.plain.{PlainModifier, PlainValue}
|
import top.davidon.sfs.dom.plain.{PlainModifier, PlainValue}
|
||||||
import top.davidon.sfs.dom.reactive.{
|
import top.davidon.sfs.dom.reactive.{
|
||||||
Observable,
|
|
||||||
ReactiveModifier,
|
ReactiveModifier,
|
||||||
ReactiveValue
|
ReactiveValue
|
||||||
}
|
}
|
||||||
|
@ -18,16 +18,16 @@ class Modifier[F, T] protected (
|
||||||
object Modifier {
|
object Modifier {
|
||||||
def fromVorObservableV[F, T](
|
def fromVorObservableV[F, T](
|
||||||
key: Key,
|
key: Key,
|
||||||
value: F | Observable[F],
|
value: F | Signal[F],
|
||||||
codec: Codec[F, T]
|
codec: Codec[F, T]
|
||||||
): Modifier[F, T] = {
|
): Modifier[F, T] = {
|
||||||
value match {
|
value match {
|
||||||
case _: F =>
|
case _: F =>
|
||||||
PlainModifier(key, PlainValue(value.asInstanceOf[F], codec))
|
PlainModifier(key, PlainValue(value.asInstanceOf[F], codec))
|
||||||
case _: Observable[F] =>
|
case _: Signal[F] =>
|
||||||
ReactiveModifier(
|
ReactiveModifier(
|
||||||
key,
|
key,
|
||||||
ReactiveValue(value.asInstanceOf[Observable[F]], codec)
|
ReactiveValue(value.asInstanceOf[Signal[F]], codec)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
package top.davidon.sfs.dom.reactive
|
|
||||||
|
|
||||||
abstract class Observable[T](var value: T) {
|
|
||||||
def subscribe(observer: T => Unit): Unit
|
|
||||||
def unsubscribe(observer: T => Unit): Unit
|
|
||||||
def update(value: T): Unit
|
|
||||||
def now(): T
|
|
||||||
}
|
|
|
@ -1,11 +1,12 @@
|
||||||
package top.davidon.sfs.dom.reactive
|
package top.davidon.sfs.dom.reactive
|
||||||
|
|
||||||
|
import rescala.default.Signal
|
||||||
import top.davidon.sfs.dom.Value
|
import top.davidon.sfs.dom.Value
|
||||||
import top.davidon.sfs.dom.codecs.Codec
|
import top.davidon.sfs.dom.codecs.Codec
|
||||||
import top.davidon.sfs.dom.plain.PlainValue
|
import top.davidon.sfs.dom.plain.PlainValue
|
||||||
|
|
||||||
class ReactiveValue[F, T](
|
class ReactiveValue[F, T](
|
||||||
val reactiveValue: Observable[F],
|
val reactiveValue: Signal[F],
|
||||||
codec: Codec[F, T]
|
codec: Codec[F, T]
|
||||||
) extends Value[F, T](reactiveValue.now(), codec) {
|
) extends Value[F, T](reactiveValue.now(), codec) {
|
||||||
override def apply(): T = {
|
override def apply(): T = {
|
||||||
|
|
|
@ -55,7 +55,7 @@ class ClientSideRenderer(val root: dom.Element) extends Renderer[Unit] {
|
||||||
m.value
|
m.value
|
||||||
.asInstanceOf[ReactiveValue[?, ?]]
|
.asInstanceOf[ReactiveValue[?, ?]]
|
||||||
.reactiveValue
|
.reactiveValue
|
||||||
.subscribe(value => { modifierFunc(el, m) })
|
.observe({ value => modifierFunc(el, m) })
|
||||||
}
|
}
|
||||||
case _: EventProp[?] =>
|
case _: EventProp[?] =>
|
||||||
el.addEventListener(
|
el.addEventListener(
|
||||||
|
@ -67,14 +67,14 @@ class ClientSideRenderer(val root: dom.Element) extends Renderer[Unit] {
|
||||||
m.value
|
m.value
|
||||||
.asInstanceOf[ReactiveValue[?, ?]]
|
.asInstanceOf[ReactiveValue[?, ?]]
|
||||||
.reactiveValue
|
.reactiveValue
|
||||||
.subscribe(value => { modifierFunc(el, m) })
|
.observe({ value => modifierFunc(el, m) })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
valueFunc(el, element.children)
|
valueFunc(el, element.children)
|
||||||
element.children.foreach { case r: ReactiveValue[?, String] =>
|
element.children.foreach { case r: ReactiveValue[?, String] =>
|
||||||
r.reactiveValue.subscribe(value => { valueFunc(el, element.children) })
|
r.reactiveValue.observe({ value => valueFunc(el, element.children) })
|
||||||
}
|
}
|
||||||
|
|
||||||
parent.append(el)
|
parent.append(el)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue