All Downloads are FREE. Search and download functionalities are using the official Maven repository.

crystal.react.package.scala Maven / Gradle / Ivy

There is a newer version: 0.45.2
Show newest version
// Copyright (c) 2016-2023 Association of Universities for Research in Astronomy, Inc. (AURA)
// For license information see LICENSE or https://opensource.org/licenses/BSD-3-Clause

package crystal.react

import cats.arrow.FunctionK
import cats.~>
import crystal.*
import crystal.react.reuse.Reuse
import crystal.react.syntax.*
import japgolly.scalajs.react.*
import japgolly.scalajs.react.util.DefaultEffects.Async as DefaultA
import japgolly.scalajs.react.util.DefaultEffects.Sync as DefaultS
import japgolly.scalajs.react.util.Effect.UnsafeSync
import japgolly.scalajs.react.vdom.VdomNode

import scala.concurrent.duration.FiniteDuration
import scala.reflect.ClassTag

type SetState[F[_], A] = A => F[Unit]
type ModState[F[_], A] = (A => A) => F[Unit]

type ContextComponent[S, B] =
  ScalaComponent[
    Reuse[VdomNode],
    S,
    B,
    CtorType.Props
  ]

type StateComponent[S, B] =
  ScalaComponent[Reuse[View[S] => VdomNode], S, B, CtorType.Props]

type View[A]     = ViewF[DefaultS, A]
type ViewOpt[A]  = ViewOptF[DefaultS, A]
type ViewList[A] = ViewListF[DefaultS, A]

type ReuseViewF[F[_], A]     = Reuse[ViewF[F, A]]
type ReuseViewOptF[F[_], A]  = Reuse[ViewOptF[F, A]]
type ReuseViewListF[F[_], A] = Reuse[ViewListF[F, A]]

type ReuseView[A]     = Reuse[View[A]]
type ReuseViewOpt[A]  = Reuse[ViewOpt[A]]
type ReuseViewList[A] = Reuse[ViewList[A]]

type ViewThrottler[A]  = ViewThrottlerF[DefaultS, DefaultA, A]
type ThrottlingView[A] = ThrottlingViewF[DefaultS, DefaultA, A]

export crystal.react.syntax.all.*, crystal.react.syntax.all.given

val syncToAsync: DefaultS ~> DefaultA = new FunctionK[DefaultS, DefaultA] { self =>
  def apply[A](fa: DefaultS[A]): DefaultA[A] = fa.toAsync
}

def View[A](
  value: A,
  modCB: (A => A, (A, A) => DefaultS[Unit]) => DefaultS[Unit]
): View[A] = ViewF[DefaultS, A](value, modCB)

def fromState = new FromStateView

class FromStateView {
  def apply[S]($ : StateAccess[DefaultS, DefaultA, S])(using
    dispatch: UnsafeSync[DefaultS]
  ): View[S] =
    View[S](
      dispatch.runSync($.state),
      (f, cb) =>
        $.state >>= (oldState => $.modState(f, $.state.flatMap(newState => cb(oldState, newState))))
    )
}

object ReuseView {
  inline def apply[A: ClassTag: Reusability](
    value: A,
    modCB: (A => A, (A, A) => DefaultS[Unit]) => DefaultS[Unit]
  ): ReuseView[A] =
    View(value, modCB).reuseByValue

  def fromState = new FromStateReuseView
}

class FromStateReuseView {
  def apply[S: ClassTag: Reusability]($ : StateAccess[DefaultS, DefaultA, S])(using
    dispatch: UnsafeSync[DefaultS]
  ): ReuseView[S] =
    ReuseView[S](
      dispatch.runSync($.state),
      (f, cb) =>
        $.state >>= (oldState => $.modState(f, $.state.flatMap(newState => cb(oldState, newState))))
    )
}

def ViewThrottler[A](timeout: FiniteDuration): DefaultA[ViewThrottler[A]] =
  ViewThrottlerF[DefaultS, DefaultA, A](timeout, syncToAsync, _.runAsyncAndForget)




© 2015 - 2024 Weber Informatics LLC | Privacy Policy