Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Copyright 2017-2020 Aleksey Fomkin
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package korolev
import korolev.Context._
import korolev.effect.Effect
import korolev.state.{StateDeserializer, StateSerializer}
import levsha.Document.Node
import scala.util.Random
/**
* Component definition. Every Korolev application is a component.
* Extent it to declare component in object oriented style.
*
* @param id Unique identifier of the component.
* Use it when you create component declaration dynamically
*
* @tparam F Control monad
* @tparam S State of the component
* @tparam E Type of events produced by component
*/
abstract class Component[
F[_],
S,
P,
E
](
val initialState: Either[P => F[S], S],
val id: String
) {
def this(initialState: S) = this(Right(initialState), Component.randomId())
def this(initialState: S, id: String) = this(Right(initialState), id)
def this(loadState: P => F[S]) = this(Left(loadState), Component.randomId())
/**
* Component context.
*
* {{{
* import context._
* }}}
*/
val context = Context[F, S, E]
/**
* Component render
*/
def render(parameters: P, state: S): context.Node
/**
* Render component while state is not loaded.
*/
def renderNoState(parameters: P): context.Node =
levsha.dsl.html.div()
/**
* Parameters may be changed.
* Maybe you want to reload state.
* The function returns optional effect.
* If no reload required it returns None,
* else it returns effect with new state.
*/
def maybeUpdateState(parameters: P, currentState: S): Option[F[S]] = None
}
object Component {
/** (context, state) => document */
type Render[F[_], S, P, E] = (Context[F, S, E], P, S) => Node[Binding[F, S, E]]
/**
* Create component in functional style
* @param f Component renderer
* @see [[Component]]
*/
def apply[F[_]: Effect, S: StateSerializer: StateDeserializer, P, E](
initialState: S,
id: String = Component.randomId())(f: Render[F, S, P, E]): Component[F, S, P, E] = {
new Component[F, S, P, E](initialState, id) {
def render(parameters: P, state: S): Node[Binding[F, S, E]] = f(context, parameters, state)
}
}
final val TopLevelComponentId = "top-level"
private[korolev] def randomId() = Random.alphanumeric.take(6).mkString
}