feat: use rescala by default for reactivity

downscale operations, supporting multiple reactive backends is too complex
This commit is contained in:
DavidOnTop 2024-10-26 21:30:59 +02:00
parent 07e4e4006a
commit ec478533c3
No known key found for this signature in database
GPG key ID: 5D05538A45D5149F
11 changed files with 35 additions and 57 deletions

View file

@ -36,7 +36,10 @@ lazy val dom = crossProject(JSPlatform, JVMPlatform)
.in(file("./dom"))
.settings(
name := "sfs-dom",
version := "0.1.0-alpha"
version := "0.1.0-alpha",
libraryDependencies ++= Seq(
"de.tu-darmstadt.stg" %% "rescala" % "0.35.1"
)
)
.jvmSettings(
libraryDependencies ++= Seq(
@ -57,26 +60,3 @@ lazy val sfs = crossProject(JSPlatform, JVMPlatform)
version := "0.1.0-alpha"
)
.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"
)

View file

@ -1,5 +1,6 @@
package top.davidon.sfs.dom
import rescala.default.Signal
import top.davidon.sfs.dom.codecs.*
import top.davidon.sfs.dom.defs.attrs.{AriaAttrs, HtmlAttrs, SvgAttrs}
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.tags.{HtmlTags, SvgTags}
import top.davidon.sfs.dom.plain.PlainValue
import top.davidon.sfs.dom.reactive.ReactiveValue
trait ScalaFullStackDOM
extends HtmlTags
@ -42,4 +44,11 @@ trait ScalaFullStackDOM
def apply(from: Iterable[String]): PlainValue[Iterable[String], String] =
PlainValue(from, IterableAsSpaceSeparatedStringCodec)
}
given signalToVal: Conversion[Signal[String], ReactiveValue[String, String]]
with {
def apply(from: Signal[String]): ReactiveValue[String, String] = {
ReactiveValue(from, StringAsIsCodec)
}
}
}

View file

@ -1,12 +1,9 @@
package top.davidon.sfs.dom.keys
import rescala.default.Signal
import top.davidon.sfs.dom.codecs.Codec
import top.davidon.sfs.dom.mods.Modifier
import top.davidon.sfs.dom.plain.{PlainModifier, PlainValue}
import top.davidon.sfs.dom.reactive.{
Observable,
ReactiveModifier,
ReactiveValue
}
import top.davidon.sfs.dom.reactive.{ReactiveModifier, ReactiveValue}
class AriaAttr[V](
suffix: String,
@ -14,11 +11,11 @@ class AriaAttr[V](
) extends Key {
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
}
def :=(value: V | Observable[V]): Modifier[V, String] = {
def :=(value: V | Signal[V]): Modifier[V, String] = {
Modifier.fromVorObservableV(this, value, codec)
}
}

View file

@ -5,7 +5,6 @@ import top.davidon.sfs.dom.Value
import top.davidon.sfs.dom.codecs.{EmptyCodec, StringAsIsCodec}
import top.davidon.sfs.dom.mods.{EventMod, Modifier}
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 {

View file

@ -1,11 +1,11 @@
package top.davidon.sfs.dom.keys
import rescala.default.Signal
import top.davidon.sfs.dom.codecs.Codec
import top.davidon.sfs.dom.Value
import top.davidon.sfs.dom.mods.Modifier
import top.davidon.sfs.dom.plain.{PlainModifier, PlainValue}
import top.davidon.sfs.dom.reactive.{
Observable,
ReactiveModifier,
ReactiveValue
}
@ -14,11 +14,11 @@ class HtmlAttr[V](
override val name: String,
val codec: Codec[V, String]
) extends Key {
@inline def apply(value: V | Observable[V]): Modifier[V, String] = {
@inline def apply(value: V | Signal[V]): Modifier[V, String] = {
this := value
}
def :=(value: V | Observable[V]): Modifier[V, String] = {
def :=(value: V | Signal[V]): Modifier[V, String] = {
Modifier.fromVorObservableV(this, value, codec)
}
}

View file

@ -1,19 +1,19 @@
package top.davidon.sfs.dom.keys
import rescala.default.Signal
import top.davidon.sfs.dom.codecs.Codec
import top.davidon.sfs.dom.Value
import top.davidon.sfs.dom.mods.Modifier
import top.davidon.sfs.dom.plain.PlainValue
import top.davidon.sfs.dom.reactive.Observable
class HtmlProp[V, DomV](
override val name: String,
val codec: Codec[V, DomV]
) extends Key {
@inline def apply(value: V | Observable[V]): Modifier[V, DomV] = {
@inline def apply(value: V | Signal[V]): Modifier[V, DomV] = {
this := value
}
def :=(value: V | Observable[V]): Modifier[V, DomV] = {
def :=(value: V | Signal[V]): Modifier[V, DomV] = {
Modifier.fromVorObservableV(this, value, codec)
}
}

View file

@ -1,7 +1,7 @@
package top.davidon.sfs.dom.keys
import rescala.default.Signal
import top.davidon.sfs.dom.codecs.Codec
import top.davidon.sfs.dom.mods.Modifier
import top.davidon.sfs.dom.reactive.Observable
class SvgAttr[V](
val localName: String,
@ -13,11 +13,11 @@ class SvgAttr[V](
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
}
def :=(value: V | Observable[V]): Modifier[V, String] = {
def :=(value: V | Signal[V]): Modifier[V, String] = {
Modifier.fromVorObservableV(this, value, codec)
}
}

View file

@ -1,11 +1,11 @@
package top.davidon.sfs.dom.mods
import rescala.default.Signal
import top.davidon.sfs.dom.Value
import top.davidon.sfs.dom.codecs.Codec
import top.davidon.sfs.dom.keys.Key
import top.davidon.sfs.dom.plain.{PlainModifier, PlainValue}
import top.davidon.sfs.dom.reactive.{
Observable,
ReactiveModifier,
ReactiveValue
}
@ -18,16 +18,16 @@ class Modifier[F, T] protected (
object Modifier {
def fromVorObservableV[F, T](
key: Key,
value: F | Observable[F],
value: F | Signal[F],
codec: Codec[F, T]
): Modifier[F, T] = {
value match {
case _: F =>
PlainModifier(key, PlainValue(value.asInstanceOf[F], codec))
case _: Observable[F] =>
case _: Signal[F] =>
ReactiveModifier(
key,
ReactiveValue(value.asInstanceOf[Observable[F]], codec)
ReactiveValue(value.asInstanceOf[Signal[F]], codec)
)
}
}

View file

@ -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
}

View file

@ -1,11 +1,12 @@
package top.davidon.sfs.dom.reactive
import rescala.default.Signal
import top.davidon.sfs.dom.Value
import top.davidon.sfs.dom.codecs.Codec
import top.davidon.sfs.dom.plain.PlainValue
class ReactiveValue[F, T](
val reactiveValue: Observable[F],
val reactiveValue: Signal[F],
codec: Codec[F, T]
) extends Value[F, T](reactiveValue.now(), codec) {
override def apply(): T = {

View file

@ -55,7 +55,7 @@ class ClientSideRenderer(val root: dom.Element) extends Renderer[Unit] {
m.value
.asInstanceOf[ReactiveValue[?, ?]]
.reactiveValue
.subscribe(value => { modifierFunc(el, m) })
.observe({ value => modifierFunc(el, m) })
}
case _: EventProp[?] =>
el.addEventListener(
@ -67,14 +67,14 @@ class ClientSideRenderer(val root: dom.Element) extends Renderer[Unit] {
m.value
.asInstanceOf[ReactiveValue[?, ?]]
.reactiveValue
.subscribe(value => { modifierFunc(el, m) })
.observe({ value => modifierFunc(el, m) })
}
}
)
valueFunc(el, element.children)
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)